*
tem um significado especial como um caractere globbing do shell ("curinga") e como um metacaractere de expressão regular . Você deve levar os dois em consideração, embora, se citar sua expressão regular, poderá impedir que o shell o trate especialmente e garantir que ele o passe inalterado grep
. Embora tipo de semelhante conceitualmente, o que *
significa que a casca é bastante diferente do que significa grep
.
Primeiro, o shell trata *
como um curinga.
Você disse:
Se a expressão está entre aspas, não faz diferença.
Isso depende de quais arquivos existem em qualquer diretório em que você esteja quando executar o comando. Para padrões que contêm o separador de diretório /
, isso pode depender de quais arquivos existem em todo o sistema. Você sempre deve citar expressões regulares para - grep
e aspas simples geralmente são melhores - a menos que tenha certeza de que está bem com os nove tipos de transformações potencialmente surpreendentes que o shell executa antes de executar o grep
comando.
Quando o shell encontra um *
caractere que não é citado , ele significa "zero ou mais de qualquer caractere" e substitui a palavra que o contém por uma lista de nomes de arquivos que correspondem ao padrão. (Os nomes de arquivos que começam com .
são excluídos - a menos que seu próprio padrão comece com .
ou você tenha configurado seu shell para incluí-los de qualquer maneira.) Isso é conhecido como globbing - e também pelos nomes expansão do nome do arquivo e expansão do nome do caminho .
O efeito grep
geralmente será que o primeiro nome de arquivo correspondente seja considerado a expressão regular - mesmo que seja óbvio para um leitor humano que ele não seja uma expressão regular - enquanto todos os outros nomes de arquivos listados automaticamente em seu glob são considerados os arquivos dentro dos quais procurar correspondências. (Você não vê a lista - ela é passada de maneira opaca grep
.) Você praticamente nunca deseja que isso aconteça.
A razão pela qual isso às vezes não é um problema - e, no seu caso particular, pelo menos até agora , não foi - é que *
será deixado sozinho se tudo o que se segue for verdadeiro :
Não havia arquivos cujos nomes correspondessem. ... Ou você desativou o globbing em seu shell, normalmente com set -f
ou equivalente set -o noglob
. Mas isso é incomum e você provavelmente saberia que fez isso.
Você está usando um shell cujo comportamento padrão é deixar em branco *
quando não há nomes de arquivos correspondentes. É o caso do Bash, que você provavelmente está usando, mas não em todos os shells no estilo Bourne. (O comportamento padrão no popular shell Zsh, por exemplo, é que os globs (a) expandam ou (b) produzam um erro.) ... Ou você alterou esse comportamento do shell - a maneira como isso é feito varia através de conchas.
Caso contrário, você não disse ao seu shell para permitir que os globs sejam substituídos por nada quando não houver arquivos correspondentes, nem falhe com uma mensagem de erro nessa situação. No Bash, isso seria feito ativando a opçãonullglob
ou failglob
shell , respectivamente.
Às vezes, você pode confiar nos itens 2 e 3, mas raramente no 1. Um grep
comando com um padrão sem aspas que funcione agora pode parar de funcionar quando você tiver arquivos diferentes ou quando você o executa em um local diferente. Cite sua expressão regular e o problema desaparece.
Em seguida, o grep
comando trata *
como um quantificador.
As outras respostas - como as de Sergiy Kolodyazhnyy e de kos - também abordam esse aspecto dessa questão, de maneiras um pouco diferentes. Por isso, incentivo aqueles que ainda não os leram a fazê-lo, antes ou depois de ler o restante desta resposta.
Supondo que o *
faça chegar ao grep - o que a citação deve garantir - grep
, significa que o item que o precede pode ocorrer várias vezes , em vez de ter que ocorrer exatamente uma vez . Ainda pode ocorrer uma vez. Ou pode não estar presente. Ou pode ser repetido. O texto que se encaixa com qualquer uma dessas possibilidades será correspondido.
O que quero dizer com "item"?
Um único personagem . Desde b
partidas um literal b
, b*
corresponde a zero ou mais b
s, portanto, ab*c
corresponde ac
, abc
, abbc
, abbbc
, etc.
Da mesma forma, uma vez que .
corresponde a qualquer caractere , .*
corresponde a zero ou mais caracteres 1 , portanto, a.*c
jogos ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, mesmo acccccchjckhcc
, etc. Ou
Uma classe de personagem . Desde [xy]
partidas x
ou y
, [xy]*
corresponde a zero ou mais caracteres, em que cada um é ou x
ou y
, portanto, p[xy]*q
corresponde a pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
, etc.
Isso também se aplica a taquigrafia formas de classes de personagens como \w
, \W
, \s
, e \S
. Como \w
corresponde a qualquer caractere de palavra, \w*
corresponde a zero ou mais caracteres de palavra. Ou
Um grupo . Desde \(bar\)
partidas bar
, \(bar\)*
corresponde a zero ou mais bar
s, portanto, foo\(bar\)*baz
corresponde foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
, etc.
Com as opções -E
ou -P
, grep
trata sua expressão regular como ERE ou PCRE , respectivamente, e não como BRE , e os grupos são cercados por em (
)
vez de \(
\)
, então você usaria em (bar)
vez de \(bar\)
e em foo(bar)baz
vez de foo\(bar\)baz
.
man grep
fornece uma explicação razoavelmente acessível da sintaxe BRE e ERE no final, além de listar todas as opções de linha de comando grep
aceitas no início. Eu recomendo essa página de manual como um recurso, e também a documentação do GNU Grep e este site de tutorial / referência (ao qual vinculei várias páginas acima).
Para testar e aprender grep
, recomendo chamá-lo com um padrão, mas sem nome de arquivo. Depois, é preciso receber informações do seu terminal. Digite linhas; as linhas que retornam para você são as que continham o texto correspondente ao seu padrão. Para sair, pressione Ctrl+ Dno início de uma linha, que sinaliza o final da entrada. (Ou você pode pressionar Ctrl+ Ccomo na maioria dos programas de linha de comando.) Por exemplo:
grep 'This.*String'
Se você usar o --color
sinalizador, grep
destacará as partes específicas de suas linhas que correspondem à sua expressão regular, o que é muito útil para descobrir o que uma expressão regular faz e para encontrar o que você procura depois de fazer. Por padrão, os usuários do Ubuntu têm um alias do Bash que causa grep --color=auto
a execução - o que é suficiente para esse fim - quando você executa a grep
partir da linha de comando, portanto, você provavelmente nem precisa passar --color
manualmente.
1 Portanto, .*
em uma expressão regular significa o que *
significa em uma concha glob. No entanto, a diferença é que grep
imprime automaticamente as linhas que contêm sua correspondência em qualquer lugar , portanto, normalmente é desnecessário ter .*
no início ou no final de uma expressão regular.
* != any number of unknown characters
ler o doc..)