
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 -e
sinalizador. Como você não está usando o -e
sinalizador, 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" file1
informa ao shell que você deseja executar grep
com o -e
argumento 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 file1
lhe 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 grep
entende como -e xample
( xample
argumento para a -e
opçã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 grep
das implementações, \-
corresponderá a -
, porém você pode imaginar grep
implementações onde \-
pode haver um operador especial (veja, por exemplo, GNU grep
onde \+
é um operador especial e não corresponde a um literal +
).
Se não quiser -example
ser 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-e
opçã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, $pattern
nã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.