Je veux grep la correspondance la plus courte et le motif devrait être quelque chose comme:
<car ... model=BMW ...>
...
...
...
</car>
... signifie n'importe quel caractère et l'entrée est multiple.
Vous recherchez un match non-gourmand (ou paresseux). Pour obtenir une correspondance non gourmande dans les expressions régulières, vous devez utiliser le modificateur ?
après le quantificateur. Par exemple, vous pouvez changer .*
à .*?
.
Par défaut, grep
ne prend pas en charge les modificateurs non gloutons, mais vous pouvez utiliser grep -P
pour utiliser la syntaxe Perl.
En réalité le .*?
ne fonctionne que dans Perl
. Je ne suis pas sûr de ce que serait la syntaxe équivalente des expressions rationnelles étendues grep. Heureusement, vous pouvez utiliser la syntaxe Perl avec grep so grep -P
fonctionnerait mais grep -E
qui est identique à egrep
ne fonctionnerait pas (ce serait gourmand).
Voir aussi: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep
Pour une correspondance non-gourmande dans grep
, vous pouvez utiliser une classe de caractères inversée. En d'autres termes, essayez d'éviter les caractères génériques.
Par exemple, pour extraire tous les liens vers les fichiers jpeg depuis le contenu de la page, utilisez:
grep -o '"[^" ]\+.jpg"'
Pour traiter plusieurs lignes, dirigez l’entrée par xargs
en premier. Pour des performances optimales, utilisez ripgrep
.
Mon grep qui fonctionne après avoir essayé des choses dans ce fil de discussion:
echo "hi how are you " | grep -shoP ".*? "
Assurez-vous simplement d'ajouter un espace à chacune de vos lignes
(Le mien était une recherche ligne par ligne pour cracher des mots)
La réponse courte utilise l'expression régulière suivante:
(?s)<car .*? model=BMW .*?>.*?</car>
Une réponse (un peu) plus compliquée est:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Cela permettra de faire correspondre car1 et car2 dans le texte suivant
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>