485 votes

Comment puis-je écrire une regex qui correspond à une correspondance non gourmande ?

J'ai besoin d'aide concernant la correspondance d'expressions régulières avec l'option non gourmande.

Le modèle de correspondance est :

<img\s.*>

Le texte à faire correspondre est :

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

Je teste sur http://regexpal.com

Cette expression correspond à tout le texte de <img pour durer > . J'ai besoin qu'il corresponde au premier rencontré > après le premier <img donc ici, je devrais obtenir deux correspondances au lieu d'une seule.

J'ai essayé toutes les combinaisons de non gourmand ? sans succès.

7 votes

Dans quelle langue exécutez-vous la REGEX ?

680voto

Pavan Manjunath Points 10853

Le non gourmand ? fonctionne parfaitement bien. C'est juste que vous devez sélectionner dot correspond à tous dans les moteurs regex ( regexpal le moteur que vous avez utilisé possède également cette option) que vous testez. En effet, les moteurs regex ne correspondent généralement pas aux sauts de ligne lorsque vous utilisez l'option . . Vous devez leur dire explicitement que vous voulez aussi faire correspondre les sauts de ligne avec .

Par exemple,

<img\s.*?>

fonctionne bien !

Vérifiez le résultats ici .

Lisez également ce qui suit comment point se comporte comme suit : dans différentes versions de regex.

47 votes

Il existe également une astuce qui permet de contourner ce problème : Puisque \s signifie "tout espace blanc", et " \S "signifie "tout espace non blanc", [ \s\S ] correspondra à N'IMPORTE QUEL caractère (comme ".", mais y compris une nouvelle ligne) ! De même, vous pouvez utiliser [ \d\D ], ou [ \w\W ]. Cela peut être un petit "hack" très pratique, et c'est certainement une astuce très utile à connaître.

15 votes

Ou même, dans cet exemple, vous pourriez utiliser : <img[^>]*> pour obtenir le même effet : puisque "Tout personnage autre que > " INCLUT une nouvelle ligne !

2 votes

Bonne réponse, mais pourquoi pas bash ? echo "<img src=test>bla<img src=a>" | grep -P '<img \s. *?>' correspond à la chaîne entière malgré l'opérateur ?

139voto

Ilya Points 306

El ? rend la correspondance non avide. Par exemple .* est gourmand alors que .*? ne l'est pas. Vous pouvez donc utiliser quelque chose comme <img.*?> pour correspondre à l'ensemble du tag. Ou <img[^>]*> .

Mais n'oubliez pas que l'ensemble du code HTML ne peut pas être analysé avec des expressions régulières.

9 votes

Votre réponse a rappelé ceci : stackoverflow.com/a/1732454/431

12 votes

Je pense que c'est plus clair de dire que *? est la version non avide de * .

30voto

tripleee Points 28746

Les autres réponses présupposent que vous disposez d'un moteur regex qui prend en charge la correspondance non gourmande, qui est une extension introduite dans Perl 5 et largement copiée dans d'autres langages modernes ; mais elle est loin d'être omniprésente.

De nombreux langages et éditeurs plus anciens ou plus conservateurs ne prennent en charge que les expressions régulières traditionnelles, qui ne disposent d'aucun mécanisme permettant de contrôler l'avidité de l'opérateur de répétition. * - il correspond toujours à la chaîne la plus longue possible.

L'astuce consiste alors à limiter ce qu'il est autorisé à associer en premier lieu. Au lieu de .* que vous semblez rechercher

[^>]*

qui correspond toujours à autant de quelque chose que possible ; mais le quelque chose n'est pas seulement . "tout caractère", mais plutôt "tout caractère qui n'est pas > ".

En fonction de votre application, vous pouvez ou non activer une option permettant à "tout caractère" d'inclure les nouvelles lignes.

Même si votre moteur d'expression régulière prend en charge la correspondance non avide, il est préférable d'expliquer clairement ce que vous voulez dire. Si cela es ce que vous voulez dire, vous devriez probablement le dire, au lieu de compter sur une correspondance non gourmande pour (espérons-le, probablement) faire ce que je veux dire.

Par exemple, une expression régulière avec un contexte de fin après le caractère générique comme .*?><br/> sautera par-dessus tout élément imbriqué > jusqu'à ce qu'il trouve le contexte de fin (ici, ><br/> ), même si cela nécessite de chevaucher de multiples > et des retours à la ligne si vous le permettez, où [^>]*><br/> (ou même [^\n>]*><br/> si vous devez explicitement interdire les nouvelles lignes) ne peut évidemment pas le faire et ne le fera pas.

Bien sûr, ce n'est toujours pas ce que vous voulez si vous devez faire face à <img title="quoted string with > in it" src="other attributes"> and perhaps <img title="nested tags"> mais à ce stade, vous devriez finalement renoncer à utiliser les expressions régulières pour ce type de recherche, comme nous vous l'avions dit au départ.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X