Eu observo o seguinte comportamento de grep
ao executá-lo cinco vezes:
me@asus:~/go/src/company/topology-front$ lsof |grep "READ" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md*" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md*" me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md" me@asus:~/go/src/company/topology-front$
Não consegui entender por que as duas últimas tentativas de grep
não estão retornando nenhum resultado .
Resposta
grep
padrões são expressões regulares (também conhecidas como regex, regexp, RE), expressões regulares básicas (BRE), a menos que uma das -E
/ -F
/ -P
/ -K
/ -X
opção (apenas as duas primeiras sendo padrão) é usada.
*
é um operador regexp que corresponde a 0 ou mais do átomo anterior. Por exemplo, d*
corresponde a 0 ou mais d
s. Em BREs, quando no início do padrão ou ao seguir o
ou \(
operadores regexp, ele corresponde apenas a *
literal (também é usado literalmente dentro de [...]
expressões de colchetes).
Portanto, grep "*README.md*"
corresponde a linhas que contêm um seguido por README
seguido por qualquer caractere único (o .
operador regexp) seguido por m
seguido por qualquer número de d
s. Como qualquer número inclui 0, isso “é funcionalmente equivalente a grep "*README.m"
(o que não faria diferença para quais linhas estão sendo correspondidas, apenas no que pode ser correspondido dentro da linha (que seria mostrado com a opção --color
do GNU grep
por exemplo)).
Por exemplo , corresponderia a essas 2 linhas:
*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^
(os ^
s mostrando o que dentro da linha é correspondido pela expressão regular, que você pode ver com --color
)
Aqui, parece que você está confundindo expressões regulares com padrões de curinga do shell. O *
operador curinga que corresponde a 0 ou mais caracteres pode ser escrito .*
em expressões regulares. Mas fazer:
grep ".*README\.md.*"
seria novamente o mesmo que:
grep "README\.md"
Como grep
procura uma correspondência dentro da linha em vez de encontrar linhas que correspondam exatamente ao padrão (para o qual você precisa -x
).
Com ast-open grep
, que também é ksh93
“s grep
integrado (nem sempre integrado por padrão, e você precisa ativá-lo colocando /opt/ast/bin
à frente de $PATH
), você pode usar a opção -K
para grep
usar curingas shell (ksh93 estendidos). Com isso grep
implementação, você pode fazer:
grep -K "README.md"
ou
grep -xK "*README.md*"
para corresponder em linhas que contêm README.md
.
Com a mesma implementação, a correspondência de curinga também pode ser ativada em estendido (), aumentada (-X
) ou semelhante a perl (-P
) regular expressões com o operador (?K)
(e \(?K\)
em expressões regulares básicas que realmente quebram a conformidade com POSIX, então eu não confiaria nisso como pode ser removido em uma versão futura). Então você pode fazer:
grep -xE "(?K)*README.md*"
lá.
Com qualquer implementação grep
moderna, você também pode fazer:
grep -F README.md
Para uma pesquisa de string fixa (onde .
acima corresponde a um .
em vez de qualquer caractere).
*
ou+
no início do regex, e o mesmo acontece comgrep -P
grep -E
com várias implementações. Aquele*
tratado literalmente quando no início é especificado apenas para BREs. Com outros REs, YMMV.grep
simples (ougrep -G
) também.grep -K
que usa padrões de shell (onde*
corresponde a qualquer número de caracteres).*
não ser especial quando o primeiro caractere de um BRE, consulte a especificação POSIX