Por que o grep não retorna o que espero quando uso aspas simples

Por que o grep não retorna o que espero quando uso aspas simples

Eu tenho um arquivo com o conteúdo abaixo:

sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!

Ao procurar por “-example” no arquivo acima, o comando grep não fornece a saída desejada. Eu sei que se o padrão contém '-' então a opção -e deve ser usada:

No primeiro exemplo usei-exemplodiretamente sem aspas:

sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example

-exemplocom aspas simples:

sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example

-exemplocom aspas duplas e caracteres de escape

sh-4.2$ grep "\-example" file1
-example
sh-4.2$

Responder1

Bem, você sabe que o padrão de pesquisa contém um '-' e sabe que quando o padrão de pesquisa contém um '-' você precisa usar o -esinalizador. Como você não está usando o -esinalizador, o shell está interpretando seu "padrão" como um argumento (e um parâmetro). Você pode ver isso com:

$ grep "-foo" file1
grep: oo: No such file or directory

Por extensão, seu código grep "-example" file1informa ao shell que você deseja executar grepcom o -eargumento e um parâmetro "xample".

Este é o mesmo problema que encontramos quando tentamos algo como rm -my-silly-file-name- não funciona e precisamos usar algo como rm ./-my-silly-file-name. Outra solução alternativa seria rm -- -my-silly-file-name. Podemos usar esse idioma aqui:

$ grep -- "-example" < file1
-example

O "--" diz ao shell que tudo depois dele énãoum argumento.

Alternativamente, você pode simplesmente escapar do "-" com um "\", como você viu:

grep "\-example" file1

Este artigo fornece alguns detalhes sobre como citar: a parte relevante éParâmetros e comandos entre aspas que devem ser interpretados pelo shell são colocados entre aspas duplas.Quando você usa aspas duplas, o conteúdo é interpretado pelo shell.

Responder2

Você "sabe se o padrão [começa com] '-' então a opção -e deve ser usada", mas não o está usando quando deveria. grep -e -example file1lhe dará o resultado esperado.

Aqui está o que é realmente executado em cada um dos seus exemplos:

  • grep -example file1=> grep -e xample file1(-e é necessário)
  • grep '-example' file1=> grep -e xample file1(-e é necessário)
  • grep "\-example" file1=> grep \-example file1(-e não é necessário)

Responder3

Um argumento que começa com -é considerado uma opção.

Nos seus dois primeiros casos, o primeiro argumento passado para grepé -example, que grepentende como -e xample( xampleargumento para a -eopção, então procure por xample).

No terceiro caso \-exampleé passado para grep. Como não começa com -, não é considerado uma opção. Em vez disso, é considerado um regexp. No entanto, o comportamento de \-não é especificado de acordo com o POSIX, portanto você não tem garantia sobre o que ele corresponde. Com a maioria grepdas implementações, \-corresponderá a -, porém você pode imaginar grepimplementações onde \-pode haver um operador especial (veja, por exemplo, GNU greponde \+é um operador especial e não corresponde a um literal +).

Se não quiser -exampleser considerado uma opção, você precisa:

  • grep -- -example file. Isso --marca o fim das opções. Qualquer coisa depois disso não é uma opção (portanto, o primeiro argumento é o padrão a ser pesquisado e o restante a lista de arquivos a serem pesquisados).
  • grep -e -example file. Aqui, -exampleé tomado como argumento para a -eopção.

Esse é o motivo pelo qual você deve se acostumar a escrever:

grep -e "$pattern" file

Ou

grep -- "$pattern" file

se você não pode garantir, $patternnão começará com -.

Observe que aqui você também pode escrever:

grep '[-]example' file

Embora vejaExpressão de colchetes (sem intervalos) correspondendo a caracteres inesperados no bashsobre possíveis complicações com essa abordagem.

informação relacionada