Hoe kan ik een regex schrijven die overeenkomt met niet-greedy?

Ik heb hulp nodig bij het matchen van reguliere expressies met een niet-hebzuchtige optie.

Het overeenkomstpatroon is:

<img\s.*>

De te matchen tekst is:

<html>
<img src="test">
abc
<img
  src="a" src='a' a=b>
</html>

Ik test op http://regexpal.com

Deze uitdrukking komt overeen met alle tekst van <img tot laatste >. Ik wil dat het overeenkomt met de eerste gevonden > na de eerste <img, dus hier zou ik twee overeenkomsten moeten krijgen in plaats van degene die ik krijg.

Ik heb alle combinaties van niet-hebzuchtige ? geprobeerd, zonder succes.


Antwoord 1, autoriteit 100%

De niet-gretige ? werkt prima. Het is alleen dat je de optie dot matcht all moet selecteren in de regex-engines (regexpal, de engine die je gebruikte, heeft ook deze optie) waarmee je aan het testen bent. Dit komt omdat regex-engines over het algemeen niet overeenkomen met regeleinden wanneer u . gebruikt. Je moet ze expliciet vertellen dat je ook regeleinden wilt matchen met .

Bijvoorbeeld

<img\s.*?>

werkt prima!

Bekijk hier de resultaten.

Lees ook over hoe dot zich gedraagt in verschillende regex-smaken.


Antwoord 2, autoriteit 19%

De ? operand maakt match niet-greedy. bijv. .* is hebzuchtig, terwijl .*? dat niet is. U kunt dus iets als <img.*?> gebruiken om de hele tag te matchen. Of <img[^>]*>.

Maar onthoud dat de hele set HTML niet kan worden geparseerd met reguliere expressies.


Antwoord 3, autoriteit 4%

De andere antwoorden hier veronderstellen dat je een regex-engine hebt die non-greedy matching ondersteunt, wat een extensie is die in Perl 5 is geïntroduceerd en op grote schaal is gekopieerd naar andere moderne talen; maar het is zeker niet alomtegenwoordig.

Veel oudere of meer conservatieve talen en editors ondersteunen alleen traditionele reguliere expressies, die geen mechanisme hebben om de hebzucht van de herhalingsoperator * te controleren – het komt altijd overeen met de langst mogelijke string.

De truc is dan om te beperken wat het in de eerste plaats mag evenaren. In plaats van .* lijkt u te zoeken naar

[^>]*

die nog steeds overeenkomt met zoveel mogelijk iets; maar het iets is niet alleen . “elk teken”, maar in plaats daarvan “elk teken dat niet >” is.

Afhankelijk van je toepassing, wil je misschien wel of niet een optie inschakelen om “elk teken” toe te staan ​​om nieuwe regels op te nemen.

Zelfs als uw engine voor reguliere expressies non-greedy matching ondersteunt, is het beter om uit te leggen wat u eigenlijk bedoelt. Als dit is wat je bedoelt, moet je dit waarschijnlijk zeggen, in plaats van te vertrouwen op niet-hebzuchtige overeenkomsten met (hopelijk, waarschijnlijk) Doen wat ik bedoel.

Bijvoorbeeld, een reguliere expressie met een afsluitende context na het jokerteken, zoals .*?><br/> springt over een geneste > totdat het vindt de volgcontext (hier, ><br/>), zelfs als dat vereist dat meerdere >-instanties en nieuwe regels over het hoofd worden gezien als u het toestaat, waarbij [^>]*><br/> (of zelfs [^\n>]*><br/> als je expliciet moet weigeren newline) kan en wil dat natuurlijk niet.

Natuurlijk is dit nog steeds niet wat je wilt als je moet omgaan met <img title="quoted string with > in it" src="other attributes"> and perhaps <img title="nested tags">, maar op dat moment moet je eindelijk stoppen met het gebruik van reguliere expressies hiervoor, zoals we je in de eerste plaats allemaal vertelden.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

2 × five =

Other episodes