grep et échapper à un signe dollar

31

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 $Idest coloré dans la sortie, c'est à dire qu'il a été apparié.

Comment pourrais-je faire correspondre le second $et pourquoi ne \$Id\$fonctionne pas .

Peu importe que le second $soit le dernier caractère ou non.

J'utilise grep2.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 grep \$Idpourquoi grep \\$Id\\$ça marche et pourquoi pas.

Je suis un peu confuse...

Luc M
la source

Réponses:

25

Il y a 2 problèmes distincts ici.

  1. greputilise les 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 de ceci est que les 2 instances de $in $Id$ne sont pas égales. Le premier est un caractère normal et le second est une ancre qui correspond à la fin de la ligne. Pour faire de la deuxième $correspondance un littéral, $vous devrez y faire une barre oblique inverse, 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: la citation de shell et la citation inverse de regex. 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 gâchis impliquant des doubles barres obliques inverses, mais je ne recommande pas d'utiliser des barres obliques inverses pour le 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 mettre d'abord votre expression régulière entière entre guillemets simples comme dans 'regex'. Le guillemet simple est la forme la plus forte de citation du shell, donc tant que votre regex 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 le regex ( \$Id\$) correct entre guillemets simples. Ce qui suit devrait faire ce que vous voulez:

grep '\$Id\$' my_dir/my_file

La raison pour laquelle \$Id\$cela ne fonctionne pas est qu'après l'application de la suppression des citations du shell (la façon la plus correcte de dire les citations du shell), l'expression régulière qui le grepvoit est $Id$. Comme expliqué dans (1.), cette expression régulière ne correspond à un littéral $Idqu'à la fin d'une ligne car la première $est littérale tandis que la seconde est un caractère d'ancrage spécial.

¹ Notez également que si vous passez à des expressions régulières étendues (ERE), par exemple si vous avez décidé d'utiliser egrep(ou grep -E), le $caractère est toujours spécial. Dans les ERE, $Id$cela ne correspondrait jamais à rien parce que vous ne pouvez pas avoir de caractères après la fin d'une ligne, ce \$Id\$serait donc la seule façon de procéder.

jw013
la source
3
Pour éviter que grep interprète son 1er paramètre comme une expression régulière, vous pouvez également le faire grep -F '$Id$'.
jfg956
Dans ma coquille (bash 4.3.42) grep '$Id\$' ...et grep \$Id\\$ ...travail
nitsas
2
Et si cela est une commande dans un makefile, vous devez également échapper à l' $un précédent $: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune
-2

Pour rechercher $Id$dans un fichier: vous pouvez utiliser:grep '\$id*' filename

Bala
la source
2
Cela correspondra à tout ce qui commence par $id, donc $ideapar exemple aussi, pas seulement $id$.
terdon