Se eu grep um documento que contém o seguinte:
ThisExampleString
... para a expressão This*String
ou *String
, nada é retornado. No entanto, This*
retorna a linha acima conforme o esperado.
Se a expressão está entre aspas, não faz diferença.
Eu pensei que o asterisco indicava algum número de caracteres desconhecidos? Por que isso só funciona se estiver no início da expressão? Se esse é o comportamento pretendido, o que eu uso em vez das expressões This*String
e *String
?
command-line
bash
grep
regex
Trae
fonte
fonte
* != any number of unknown characters
ler o doc..)Respostas:
Um asterisco em expressões regulares significa "corresponder ao elemento anterior 0 ou mais vezes".
No seu caso particular
grep 'This*String' file.txt
, você está tentando dizer: "ei, grep, combine-me com a palavraThi
, seguida des
zero em minúsculas ou mais vezes, seguida da palavraString
". As minúsculass
não são encontradas em nenhum lugarExample
, portanto o grep ignoraThisExampleString
.No caso de
grep '*String' file.txt
, você está dizendo "grep, combine-me com a string vazia - literalmente nada - precedendo a palavraString
". Claro, nãoThisExampleString
é assim que se deve ler. (Existem outros significados possíveis - você pode tentar isso com e sem a-E
bandeira - mas nenhum dos significados é parecido com o que você realmente deseja aqui.)Sabendo que
.
significa "qualquer caractere único", que poderia fazer isso:grep 'This.*String' file.txt
. Agora, o comando grep irá lê-lo corretamente:This
seguido por qualquer caractere (pense nele como uma seleção de caracteres ASCII) repetido várias vezes, seguido porString
.fonte
*
existe um caractere especial e deve ser citado ou escapado, por exemplo, como este:grep 'This*String' file.txt
ou isto:grep This\*String file.txt
para não ser surpreendido por resultados inesperados.*
é um curinga. No grep,*
é um operador de expressão regular. Veja unix.stackexchange.com/q/57957/70524strace grep .* file.txt |& head -n 1
estrace grep '.*' file.txt |& head -n 1
. Também realmentegrep
funciona também com qualquer caractere Unicode (por exemplo,echo -ne ⇏ | grep ⇏
saídas⇏
)bash
. Isso significa que primeirobash
interpreta seus caracteres especiais e somente depois de todas as expansões executadas, ele passa os parâmetros para o processo gerado. ----- Por exemplo, este comando no Bash:grep This.\*String file.txt
vão aparecer/bin/grep
com esses parâmetros 0:grep
, 1:This.*String
2:file.txt
. Observe que o Bash removeu a barra invertida e o originalmente escapado*
foi passado literalmente.grep This.*String file.txt
normalmente funcionam porque provavelmente não haverá um arquivo correspondente à expressão curinga do shellThis.*String
. Nesse caso, por padrão, o Bash passa o argumento literalmente incluindo*
.O
*
metacaractere em BRE 1 s, ERE 1 se PCRE 1 s corresponde a 0 ou mais ocorrências do padrão agrupado anteriormente (se um padrão agrupado estiver precedendo o*
metacaractere), 0 ou mais ocorrências da classe anterior de caracteres (se uma classe de caractere for precedendo o*
metacaractere) ou 0 ou mais ocorrências do caractere anterior (se nem um padrão agrupado nem uma classe de caractere estiverem precedendo o*
metacaractere);Isso significa que, no
This*String
padrão, sendo o*
metacaractere não precedido por um padrão agrupado ou por uma classe de caracteres, o*
metacaractere corresponde a 0 ou mais ocorrências do caractere anterior (neste caso, os
caractere):Para corresponder a 0 ou mais ocorrências de qualquer caractere, você deseja corresponder a 0 ou mais ocorrências do
.
metacaractere, que corresponde a qualquer caractere:O
*
metacaractere em BREs e EREs é sempre "ganancioso", ou seja, corresponderá à correspondência mais longa:Este pode não ser o comportamento desejado; caso contrário, você pode ativar
grep
o mecanismo PCRE (usando a-P
opção) e anexar o?
metacaractere, que quando colocado após os metacaracteres*
e+
tem o efeito de alterar sua ganância:1: Expressões regulares básicas, expressões regulares estendidas e expressões regulares compatíveis com Perl
fonte
Uma das explicações encontradas aqui link :
fonte
*
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 inalteradogrep
. Embora tipo de semelhante conceitualmente, o que*
significa que a casca é bastante diferente do que significagrep
.Primeiro, o shell trata
*
como um curinga.Você disse:
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 ogrep
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 opacagrep
.) 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 equivalenteset -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ção
nullglob
oufailglob
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 literalb
,b*
corresponde a zero ou maisb
s, portanto,ab*c
correspondeac
,abc
,abbc
,abbbc
, etc.Da mesma forma, uma vez que
.
corresponde a qualquer caractere ,.*
corresponde a zero ou mais caracteres 1 , portanto,a.*c
jogosac
,akc
,ahjglhdfjkdlgjdfkshlgc
, mesmoacccccchjckhcc
, etc. OuUma classe de personagem . Desde
[xy]
partidasx
ouy
,[xy]*
corresponde a zero ou mais caracteres, em que cada um é oux
ouy
, portanto,p[xy]*q
corresponde apq
,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. OuUm grupo . Desde
\(bar\)
partidasbar
,\(bar\)*
corresponde a zero ou maisbar
s, portanto,foo\(bar\)*baz
correspondefoobaz
,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 emfoo(bar)baz
vez defoo\(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 comandogrep
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: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 causagrep --color=auto
a execução - o que é suficiente para esse fim - quando você executa agrep
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 é quegrep
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.fonte