grep e escapando de um cifrão

31

Quero saber quais arquivos têm a string $Id$.

grep \$Id\$  my_dir/mylist_of_files

retorna 0 ocorrências.

Eu descobri que tenho que usar

grep \$Id$ my_dir/mylist_of_files

Então eu vejo que o $Idcolorido está na saída, ou seja, foi correspondido.

Como eu poderia combinar o segundo $e por que não \$Id\$funciona.

Não importa se o segundo $é o último caractere ou não.

Eu uso grep2,9.


Antes de postar minha pergunta, eu usei o google ...

Eu encontrei uma resposta

Para procurar um $ (cifrão) no arquivo chamado test2, digite:

grep \\ $ test2

Os caracteres \\ (barra invertida dupla) são necessários para forçar o shell a passar um \ $ (barra invertida única, sinal de dólar) ao comando grep. O caractere \ (barra invertida única) informa ao comando grep para tratar o seguinte caractere (neste exemplo, o $) como um caractere literal em vez de um caractere de expressão. Use o comando fgrep para evitar a necessidade de usar caracteres de escape, como a barra invertida.

mas não entendo por que grep \$Idfunciona e por grep \\$Id\\$que não.

Eu estou um pouco confuso...

Luc M
fonte

Respostas:

25

Há duas questões separadas aqui.

  1. grepusa expressões regulares básicas (BRE) e $é um caractere especial nos BREs somente no final de uma expressão. A conseqüência disso é que as 2 instâncias de $in $Id$não são iguais. O primeiro é um caractere normal e o segundo é uma âncora que corresponde ao final da linha. Para tornar a segunda $correspondência literal, $você terá que escapar pela barra invertida, ou seja $Id\$. Escapar do primeiro $também funciona :, \$Id\$e eu prefiro isso, pois parece mais consistente.¹

  2. Existem dois mecanismos de escape / citação completamente independentes em ação aqui: citação de shell e citação de barra invertida regex. O problema são muitos caracteres que as expressões regulares usam também são especiais para o shell e, além disso, o caractere de escape regex, a barra invertida, também é um caractere de citação do shell. É por isso que você costuma ver bagunças envolvendo barras invertidas duplas, mas eu não recomendo o uso de barras invertidas para o shell que cite expressões regulares, porque não é muito legível.

    Em vez disso, a maneira mais simples de fazer isso é colocar primeiro todo o seu regex entre aspas simples, como em 'regex'. A aspas simples é a forma mais forte de citar o shell, portanto, desde que o seu regex não contenha aspas simples, você não precisa mais se preocupar com a citação do shell e pode se concentrar na sintaxe pura do BRE.

Portanto, aplicando isso de volta ao seu exemplo original, vamos lançar o regex ( \$Id\$) correto entre aspas simples. A seguir, faça o que você deseja:

grep '\$Id\$' my_dir/my_file

O motivo \$Id\$não funciona é que, após a remoção da cotação do shell (a maneira mais correta de dizer a citação do shell) é aplicada, o regex que grepvê é $Id$. Conforme explicado em (1.), esse regex corresponde a um literal $Idapenas no final de uma linha, porque o primeiro $é literal enquanto o segundo é um caractere de âncora especial.

Also Observe também que, se você mudar para Expressões regulares estendidas (ERE), por exemplo, se você decidir usar egrep(ou grep -E), o $caractere será sempre especial. Nos EREs $Id$nunca corresponderia a nada, porque você não pode ter caracteres após o final de uma linha, portanto \$Id\$seria o único caminho a percorrer.

jw013
fonte
3
Para evitar que o grep interprete seu primeiro parâmetro como uma expressão regular, você também pode fazer grep -F '$Id$'.
Jfg956
No meu shell (bash 4.3.42) grep '$Id\$' ...e grep \$Id\\$ ...trabalho
nitsas
2
E se este é um comando em um makefile, você também deve escapar o $com um precedente $: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune
-2

Para pesquisar $Id$em um arquivo: você pode usar:grep '\$id*' filename

Bala
fonte
2
Isso corresponderá a qualquer coisa que comece com $id, $ideapor exemplo, também, não apenas $id$.
terdon