web-dev-qa-db-fra.com

grep et échapper à un signe dollar

Je veux savoir quels fichiers ont la chaîne $Id$.

grep \$Id\$  my_dir/mylist_of_files

renvoie 0 occurrence.

J'ai découvert que je dois utiliser

grep \$Id$ my_dir/mylist_of_files

Ensuite, je vois que le $Id est coloré dans la sortie, c'est-à-dire qu'il a été mis en correspondance.

Comment pourrais-je faire correspondre le deuxième $ et pourquoi pas \$Id\$ travail.

Peu importe si le deuxième $ est le dernier caractère ou non.

J'utilise grep 2.9.


Avant de poster ma question, j'ai utilisé google ...

j'ai trouvé une réponse

Pour rechercher un $ (signe dollar) dans le fichier nommé test2, entrez:

grep \\ $ test2

Les caractères \\ (double barre oblique inverse) sont nécessaires pour forcer le shell à passer un\$ (barre oblique inverse simple, signe dollar) à la commande grep. Le caractère\(barre oblique inverse) indique à la commande grep de traiter le caractère suivant (dans cet exemple, le $) comme un caractère littéral plutôt que comme un caractère d'expression. Utilisez la commande fgrep pour éviter d'avoir à utiliser des caractères d'échappement tels que la barre oblique inverse.

mais je ne comprends pas pourquoi grep \$Id fonctionne et pourquoi grep \\$Id\\$ non.

Je suis un peu confuse...

33
Luc M

Il y a 2 problèmes distincts ici.

  1. grep utilise Expressions régulières de base (BRE) et $ est un caractère spécial dans les BRE uniquement à la fin d'une expression. La conséquence en est que les 2 instances de $ dans $Id$ ne sont pas égaux. Le premier est un caractère normal et le second est une ancre qui correspond à la fin de la ligne. Pour faire le deuxième $ correspond à un littéral $ vous devrez utiliser une barre oblique inverse pour y échapper, c'est-à-dire $Id\$. Échapper au premier $ fonctionne également: \$Id\$, et je préfère cela car il semble plus cohérent.¹

  2. Il y a deux mécanismes d'échappement/de citation complètement indépendants à l'œuvre ici: Shell quoting et regex backslash quoting. Le problème est que de nombreux caractères utilisés par les expressions régulières sont également spéciaux pour le shell, et en plus de cela, le caractère d'échappement d'expression régulière, la barre oblique inverse, est également un caractère de guillemet du shell. C'est pourquoi vous voyez souvent des dégâts impliquant des doubles barres obliques inverses, mais je ne recommande pas d'utiliser des barres obliques inverses pour Shell en citant des expressions régulières car elles ne sont pas très lisibles.

    Au lieu de cela, la façon la plus simple de le faire est de d'abord mettre l'intégralité de votre expression régulière entre guillemets simples comme dans 'regex'. Le guillemet simple est la forme la plus puissante de citation du Shell, donc tant que votre expression régulière ne contient pas de guillemets simples, vous n'avez plus à vous soucier des citations du Shell et pouvez vous concentrer sur la syntaxe BRE pure.

Donc, en appliquant cela à votre exemple d'origine, jetons l'expression rationnelle correcte (\$Id\$) entre guillemets simples. Ce qui suit devrait faire ce que vous voulez:

grep '\$Id\$' my_dir/my_file

La raison \$Id\$ ne fonctionne pas car après suppression de la citation de Shell (la façon la plus correcte de dire la citation de Shell), l'expression régulière que grep voit est $Id$. Comme expliqué dans (1.), cette expression régulière correspond à un $Id uniquement à la fin d'une ligne car le premier $ est littéral tandis que le second est un caractère d'ancrage spécial.

¹ Notez également que si vous passez à des expressions régulières étendues (ERE), par ex. si vous avez décidé d'utiliser egrep (ou grep -E), le $ le caractère est toujours spécial. Dans l'ERE de $Id$ ne correspondrait à rien car vous ne pouvez pas avoir de caractères après la fin d'une ligne, donc \$Id\$ serait la seule voie à suivre.

26
jw013