Je veux grep 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 sur plusieurs lignes.
Réponses:
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 .*
en .*?
.
Par défaut, grep
il ne prend pas en charge les modificateurs non gourmands, mais vous pouvez utiliser grep -P
pour utiliser la syntaxe Perl.
.
faire correspondre les nouvelles lignes est appelé DOTALL ou mode à une seule ligne ; Ruby est le seul à l'appeler multiligne . Dans les autres versions, le mode multiligne permet aux ancres ( ^
et $
) de correspondre aux limites de ligne. Ruby n'a pas de mode équivalent car dans Ruby, ils fonctionnent toujours de cette façon.
-P
était complètement nouveau pour moi, je me suis heureusement échappé pendant des années, et n'utilisais que -E
... tant d'années gaspillées! - Note à moi-même: relisez les pages Man comme une chose (encore plus!) Régulière, vous ne digérez jamais assez de commutateurs et d'options.
grep
ne prend pas en charge -P
, mais si vous utilisez, egrep
vous pouvez utiliser le .*?
modèle pour obtenir le même résultat. egrep -o 'start.*?end' text.html
-P
mais -E
appellerait egrep
donc les .*?
travaux suggérés très bien.
En fait, le .*?
seul fonctionne dans perl
. Je ne suis pas sûr de ce que serait la syntaxe équivalente de l'expression rationnelle étendue grep. Heureusement, vous pouvez utiliser la syntaxe perl avec grep, donc grep -P
cela fonctionnerait mais grep -E
qui est le même que egrep
cela ne fonctionnerait pas (ce serait gourmand).
Voir aussi: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep -P
ne fonctionne pas dans GNU grep 2.9 - il suffit de l'essayer (cela ne fait pas d'erreur, n'applique simplement pas silencieusement ?
.) La classe not non plus, par exemple:env|grep '[^\=]*\='
grep -P
option ou de pgrep
commande dans Darwin / OS X 10.8 Mountain Lion, maisegrep
fonctionne très bien.
pgrep
commande sur ma boîte OS X 10.9, mais c'est un programme complètement différent dont le but est de "trouver ou signaler des processus par leur nom".
grep
Pour une correspondance non gourmande, grep
vous pouvez utiliser une classe de caractères 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 utiliseriez:
grep -o '"[^" ]\+.jpg"'
Pour traiter plusieurs lignes, dirigez d'abord l'entrée xargs
. Pour la performance, utilisez ripgrep
.
Mon grep qui fonctionne après avoir essayé des choses dans ce fil:
echo "hi how are you " | grep -shoP ".*? "
Assurez-vous simplement d'ajouter un espace à chacune de vos lignes
(La mienne était une recherche ligne par ligne pour cracher des mots)
-shoP
nice mnemonic :)
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 paresseux explicite également.
La réponse courte utilise la prochaine expression régulière:
(?s)<car .*? model=BMW .*?>.*?</car>
Une réponse (un peu) plus compliquée est:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Cela permet de faire correspondre car1 et car2 dans le texte suivant
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
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 rechercher les mots qui commencent 'H'
et se terminent par 'o'
, avec n'importe quel nombre de caractères entre les deux. Et nous ne voulons pas de lignes, nous voulons juste des mots. Donc pour cela on peut utiliser l'expression:
grep "H[^ ]*o" file
Cela renverra tous les mots. La façon dont cela fonctionne est que: Cela permettra à tous les caractères au lieu du caractère espace entre les deux, de cette façon nous pouvons éviter plusieurs mots dans la même ligne.
Vous pouvez maintenant remplacer le caractère d'espace par tout autre caractère de votre choix. Supposons que la ligne initiale était "Hello-my-name-is-Jello"
, alors vous pouvez obtenir des mots en utilisant l'expression:
grep "H[^-]*o" file
Je sais que c'est un peu un post mort mais je viens de remarquer que cela fonctionne. Il a supprimé à la fois le nettoyage et le nettoyage de ma sortie.
> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20