grep y escapando de un signo de dólar

31

Quiero saber qué archivos tienen la cadena $Id$.

grep \$Id\$  my_dir/mylist_of_files

devuelve 0 ocurrencias.

Descubrí que tengo que usar

grep \$Id$ my_dir/mylist_of_files

Entonces veo que el $Idcolor está en la salida, es decir, ha sido emparejado.

¿Cómo podría igualar el segundo $y por qué no \$Id\$funciona?

No importa si el segundo $es el último personaje o no.

Yo uso grep2.9.


Antes de publicar mi pregunta, usé google ...

Encontré una respuesta

Para buscar un $ (signo de dólar) en el archivo llamado test2, ingrese:

grep \\ $ test2

Los caracteres \\ (doble barra invertida) son necesarios para forzar al shell a pasar un \ $ (barra invertida simple, signo de dólar) al comando grep. El carácter \ (barra diagonal inversa simple) le dice al comando grep que trate el siguiente carácter (en este ejemplo, el $) como un carácter literal en lugar de un carácter de expresión. Use el comando fgrep para evitar la necesidad de usar caracteres de escape como la barra diagonal inversa.

pero no entiendo por qué grep \$Idfunciona y por qué grep \\$Id\\$no.

Estoy un poco confundido...

Luc M
fuente

Respuestas:

25

Hay 2 problemas separados aquí.

  1. grepusa expresiones regulares básicas (BRE) y $es un carácter especial en BRE solo al final de una expresión. La consecuencia de esto es que las 2 instancias de $in $Id$no son iguales. El primero es un personaje normal y el segundo es un ancla que coincide con el final de la línea. Para hacer que la segunda $coincidencia sea literal $, tendrá que hacer una barra invertida para escapar, es decir $Id\$. Escapar al primero $también funciona: \$Id\$y prefiero esto ya que parece más consistente.

  2. Hay dos mecanismos de escape / cita completamente no relacionados en el trabajo aquí: cita de shell y cita de barra invertida regex. El problema es que muchos caracteres que usan las expresiones regulares también son especiales para el shell, y además el carácter de escape de expresiones regulares, la barra diagonal inversa, también es un carácter de comillas de shell. Esta es la razón por la que a menudo se ven desordenes que involucran barras diagonales inversas dobles, pero no recomiendo usar barras diagonales inversas para el shell que cita expresiones regulares porque no es muy legible.

    En cambio, la forma más sencilla de hacer esto es poner primero la expresión regular completa dentro de comillas simples como en 'regex'. La comilla simple es la forma más fuerte de citar el shell, por lo tanto, siempre que su expresión regular no contenga comillas simples, ya no tendrá que preocuparse por las comillas de shell y puede centrarse en la sintaxis BRE pura.

Entonces, aplicando esto a su ejemplo original, arrojemos la expresión regular correcta ( \$Id\$) dentro de comillas simples. Lo siguiente debe hacer lo que quieras:

grep '\$Id\$' my_dir/my_file

La razón \$Id\$no funciona porque después de aplicar la eliminación de comillas de shell (la forma más correcta de decir comillas de shell), la expresión regular que grepve es $Id$. Como se explica en (1.), esta expresión regular coincide con un literal $Idsolo al final de una línea porque el primero $es literal mientras que el segundo es un carácter de anclaje especial.

¹ Tenga en cuenta también que si alguna vez cambia a Expresiones regulares extendidas (ERE), por ejemplo, si decidió usar egrep(o grep -E), el $carácter siempre es especial. En ERE $Id$nunca coincidiría con nada porque no puede tener caracteres después del final de una línea, por \$Id\$lo que sería la única forma de hacerlo.

jw013
fuente
3
Para evitar que grep interprete su primer parámetro como una expresión regular, también puede hacerlo grep -F '$Id$'.
jfg956
In my shell (bash 4.3.42) grep '$Id\$' ...y grep \$Id\\$ ...work
nitsas
2
Y si esto es un comando en un archivo MAKE, también debe escapar de la $con un precedente $: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune
-2

Para buscar $Id$en un archivo: puede usar:grep '\$id*' filename

Bala
fuente
2
Eso coincidirá con cualquier cosa que comience $id, $ideapor ejemplo, no solo $id$.
terdon