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.