Problème de regex Grep 'OR'

65

J'essaie d'utiliser grep avec une expression rationnelle pour rechercher dans un fichier des lignes qui correspondent à l'une des deux chaînes possibles. Voici mon grep:

$ grep "^ID.*(ETS|FBS)" my_file.txt

Le grep ci-dessus ne renvoie aucun résultat. Cependant si j'exécute soit:

$ grep "^ID.*ETS" my_file.txt  

ou

$ grep "^ID.*FBS" my_file.txt  

Je fais correspondre des lignes spécifiques. Pourquoi mon expression rationnelle OR ne correspond-elle pas? Merci d'avance pour l'aide!

dr.bunsen
la source

Réponses:

94

Avec regex normal, les caractères (, |et )doivent être échappés. Donc vous devriez utiliser

$ grep "^ID.*\(ETS\|FBS\)" my_file.txt

Vous n’avez pas besoin des échappées lorsque vous utilisez l’ option extended regex ( -E). Voir la man grepsection " Basic vs Extended Regular Expressions".

rozcietrzewiacz
la source
10
Vous pouvez également utiliser egrepau lieu de grep -E.
Riccardo Murri le
2
@RiccardoMurri La réponse de Michal indique qu'egrep (et fgrep) sont obsolètes (même s'ils peuvent toujours fonctionner).
Timo
27

Si vous voulez utiliser plusieurs branches (le " |comme" or), alors pour être plus compatible, il est préférable de dire explicitement que vous voulez utiliser "RE moderne". AVANT.

Pour ce faire, utilisez grep -E :

grep -E "^ID.*(ETS|FBS)" my_file.txt

Pour en savoir plus sur RE, ERE et l’ensemble de l’histoire «moderne» de l’ER, voir man 7 regex.

Sinon, vous pouvez utiliser à la egrepplace de grep, mais comme vous pouvez le lire man grep:

egrep est identique à grep -E. fgrep est identique à grep -F

(...)

L'invocation directe en tant que egrep ou fgrep est obsolète

Michał Šrajer
la source
Bien que l’appel direct de egrep soit déconseillé, il fonctionnera dans la plupart des variantes * nix.
Mark D