240 votes

Grep non gourmand

Je veux récupérer la correspondance la plus courte et le modèle devrait être quelque chose comme.. :

<car ... model=BMW ...>
...
...
...
</car>

... signifie n'importe quel caractère et l'entrée est constituée de plusieurs lignes.

8 votes

390voto

Mark Byers Points 318575

Vous recherchez un partenaire non avare (ou paresseux). Pour obtenir une correspondance non avide dans les expressions régulières, vous devez utiliser le modificateur ? après le quantificateur. Par exemple, vous pouvez modifier .* à .*? .

Par défaut grep ne supporte pas les modificateurs non gourmands, mais vous pouvez utiliser grep -P pour utiliser la syntaxe Perl.

0 votes

Vous aurez également besoin du modificateur "dot all" pour que le point corresponde aux nouvelles lignes. Cette réponse est le premier résultat pour "grep dot all modifier" ... qu'est-ce que c'est ?

3 votes

Eegg : le modificateur dot all est également connu sous le nom de multiligne. C'est un modificateur qui modifie le comportement de la correspondance "." pour inclure les nouvelles lignes (ce qui n'est normalement pas le cas). Ce modificateur n'existe pas dans grep, mais il existe dans pcregrep .

2 votes

Correction : Dans la plupart des saveurs de regex qui le supportent, le mode qui permet à . pour faire correspondre les nouvelles lignes est appelée DOTALL o ligne unique Ruby est le seul à l'appeler ainsi multiligne . Dans les autres saveurs, multiligne est le mode qui permet aux ancres ( ^ y $ ) pour faire correspondre les lignes. Ruby n'a pas de mode équivalent parce qu'en Ruby, ils fonctionnent toujours de cette manière.

97voto

John Smith Points 541

En fait, le .* ? ne fonctionne qu'en perl. Je ne suis pas sûr de ce que serait la syntaxe équivalente de grep extended regexp. Heureusement, vous pouvez utiliser la syntaxe perl avec grep. Ainsi, grep -P fonctionnerait, mais grep -E, qui est identique à egrep, ne fonctionnerait pas (il serait trop gourmand).

Voir aussi : http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html

10 votes

grep -P ne fonctionne pas dans GNU grep 2.9 -- je viens de l'essayer (il n'y a pas d'erreur, mais il n'applique pas silencieusement l'option ? . Il est intéressant de noter que le pas de classe eg : env|grep '[^\=]*\='

2 votes

Il n'y a pas de grep -P ou pgrep dans Darwin/OS X 10.8 Mountain Lion, mais la commande egrep fonctionne très bien.

2 votes

Il y a un pgrep sur ma machine OS X 10.9, mais il s'agit d'un programme complètement différent dont le but est de "trouver ou signaler des processus par leur nom".

23voto

jonz Points 31

Mon grep qui fonctionne après avoir essayé des trucs dans ce fil :

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)

8 votes

-shoP bon moyen mnémotechnique :)

1 votes

echo "bbbbb" | grep -shoP 'b.*?b' est un peu une expérience d'apprentissage. La seule chose qui a fonctionné pour moi en termes de paresse explicite également.

23voto

kenorb Points 2464

grep

Pour les correspondances non recherchées dans grep vous pourriez utiliser une classe de personnage annulée. En d'autres termes, essayez d'éviter les caractères génériques.

Par exemple, pour récupérer tous les liens vers des fichiers jpeg à partir du contenu de la page, vous utiliserez :

grep -o '"[^" ]\+.jpg"'

Pour traiter les lignes multiples, il faut faire passer l'entrée par l'intermédiaire de xargs d'abord. Pour des raisons de performance, utilisez ripgrep .

6voto

mr.1n5an_e Points 51

Désolé, j'ai 9 ans de retard, mais cela pourrait fonctionner pour les téléspectateurs en 2020.

Supposons donc que vous ayez une ligne comme "Hello my name is Jello" . Vous voulez maintenant trouver les mots qui commencent par 'H' et se termine par 'o' avec n'importe quel nombre de caractères entre les deux. Et nous ne voulons pas de lignes, mais seulement des mots. Pour cela, nous pouvons utiliser l'expression :

grep "H[^ ]*o" file

Ceci renverra tous les mots. Cela fonctionne de la manière suivante : Il autorise tous les caractères au lieu du caractère d'espacement, ce qui permet d'éviter la présence de plusieurs mots dans la même ligne.

Vous pouvez maintenant remplacer le caractère espace par n'importe quel autre caractère. Supposons que la ligne initiale soit "Hello-my-name-is-Jello" Vous pouvez alors obtenir des mots à l'aide de l'expression :

grep "H[^-]*o" file

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