130 votes

Regex lookahead pour 'not followed by' dans grep

J'essaie de rechercher toutes les occurrences de Ui\. non suivi par Line ou même simplement la lettre L

Quelle est la bonne façon d'écrire une regex pour trouver toutes les instances d'une chaîne particulière NON suivie d'une autre chaîne ?

Utilisation des lookaheads

grep "Ui\.(?!L)" *
bash: !L: event not found

grep "Ui\.(?!(Line))" *
nothing

5 votes

Quelle sous-espèce de regex - PCRE, ERE, BRE, grep, ed, sed, perl, python, Java, C, ... ?

5 votes

En passant, le "événement non trouvé" provient de l'utilisation de l'expansion de l'histoire. Vous pourriez vouloir désactiver l'expansion de l'historique si vous ne l'utilisez jamais, et si vous voulez parfois pouvoir utiliser un point d'exclamation dans vos commandes interactives. set +o histexpand dans Bash ou set +H YMMV.

14 votes

J'ai également eu le problème de l'expansion de l'histoire. I pensez à J'ai résolu le problème en utilisant des guillemets simples, afin que l'interpréteur de commandes n'essaie pas d'enrichir l'argument.

186voto

Jonathan Leffler Points 299946

Le lookahead négatif, qui est ce que vous recherchez, nécessite un outil plus puissant que le standard grep . Vous avez besoin d'un grep compatible PCRE.

Si vous avez GNU grep la version actuelle prend en charge les options -P ou --perl-regexp et vous pouvez alors utiliser la regex que vous vouliez.

Si vous n'avez pas (une version suffisamment récente de) GNU grep alors envisagez de vous procurer ack .

41 votes

Je suis presque sûr que le problème dans ce cas est juste que dans bash vous devez utiliser des guillemets simples et non doubles, donc il ne traitera pas ! comme un caractère spécial.

0 votes

(voir ci-dessous ma réponse qui décrit exactement cela).

4 votes

Vérifié, la réponse correcte devrait combiner cette réponse et le commentaire de @NHDaly. Par exemple, cette commande fonctionne pour moi : grep -P '^.*contains((?!but_not_this).)*$' *.log.* >" D:\temp\result.out "

45voto

NHDaly Points 878

La réponse à une partie de votre problème est ici, et ack se comporterait de la même manière : Ack & negative lookahead donnant des erreurs

Vous utilisez des guillemets doubles pour grep, ce qui permet à bash d'"interpréter" ! comme l'histoire le commande."

Vous devez envelopper votre modèle dans des guillemets simples : grep 'Ui\.(?!L)' *

Toutefois, voir La réponse de @JonathanLeffler pour traiter les problèmes liés aux anticipations négatives dans les normes grep !

0 votes

Vous confondez la fonctionnalité d'extension de GNU grep avec la fonctionnalité de la norme grep où la norme pour grep est POSIX. Ce que vous dites est également vrai - j'exécute Bash avec les barbarismes du shell C désactivés (parce que si je voulais un shell C, j'en utiliserais un, mais je n'en veux pas), donc l'option ! Je ne suis pas concerné par ce genre de choses, mais pour obtenir des visions négatives, il faut une approche non standard. grep .

1 votes

@JonathanLeffler, merci pour la clarification ; je pense que vous avez raison de dire que nos deux réponses doivent traiter tous les symptômes du PO. Merci.

1 votes

En utilisant -E avec ce lookahead négatif, cela donne grep: repetition-operator operand invalid :(

14voto

Karel Tucek Points 26

Vous ne pouvez probablement pas effectuer des recherches négatives standard en utilisant grep, mais vous devriez normalement être en mesure d'obtenir un comportement équivalent en utilisant le commutateur "inverse" '-v'. En utilisant cette option, vous pouvez construire une regex pour le complément de ce que vous voulez faire correspondre, puis la faire passer par deux greps.

Pour la regex en question, vous pourriez faire quelque chose comme

grep 'Ui\.' * | grep -v 'Ui\.L'

1 votes

Cela exclurait plus de choses, par exemple si la ligne contient Ui.Line et Ui sans .Line.

1 votes

(Oui, c'est pourquoi je ne le formule pas strictement. Cela résout simplement une partie importante des scénarios qui orientent les gens vers ce problème, rien de plus).

1voto

Vinicius Ottoni Points 1549

Je pense que ce lien peut vous aider, d'abord à comprendre comment fonctionne la regex et ensuite, comment construire votre regex : http://www.regular-expressions.info/tutorialcnt.html

-1voto

m0skit0 Points 10269

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