Existem 2 edições separadas aqui.
-
grep
usa Expressões regulares básicas (BRE), e$
é um caractere especial no BRE apenas no final de uma expressão. A conseqüência disso é que as duas instâncias de$
em$Id$
não são iguais. O primeiro é um caractere normal e o segundo é uma âncora que corresponde ao final da linha. Para fazer com que o segundo$
corresponda a um literal$
, você terá que recuar a barra invertida, ou seja,$Id\$
. Escapar do primeiro$
também funciona:\$Id\$
, e eu prefiro isso já que parece mais consistente.¹ -
Existem dois mecanismos de escape / cotação completamente não relacionados em funcionamento aqui: o shell quoting e o regex entre aspas invertidas. O problema é que muitos caracteres que 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 de shell. É por isso que você costuma ver bagunças envolvendo barras duplas invertidas, mas eu não recomendo o uso de barras invertidas para shell citando expressões regulares, porque não é muito legível.
Em vez disso, a maneira mais simples de fazer isso é primeiro colocar toda sua regex dentro de aspas simples como em
'regex'
. A aspa simples é a forma mais strong de citar que o shell tem, portanto, contanto que o seu regex não contenha aspas simples, você não precisa mais se preocupar com o shell quoting e pode se concentrar na sintaxe pura do BRE.
Então, aplicando isso de volta ao seu exemplo original, vamos lançar a regex correta ( \$Id\$
) dentro de aspas simples. O seguinte deve fazer o que quiser:
grep '\$Id\$' my_dir/my_file
A razão \$Id\$
não funciona porque após a remoção da cotação do shell (a maneira mais correta de dizer aspas do shell) é aplicada, a regex que grep
vê é $Id$
. Como explicado em (1.), essa regex corresponde a um literal $Id
apenas no final de uma linha porque o primeiro $
é literal, enquanto o segundo é um caractere especial de âncora.
¹ Observe também que, se você mudar para expressões regulares estendidas (ERE), por exemplo, Se você decidiu usar egrep
(ou grep -E
), o caractere $
é sempre especial. Em $Id$
do ERE nunca corresponderia a nada porque você não pode ter caracteres após o final de uma linha, então \$Id\$
seria o único caminho a seguir.