O uso de curingas no início da expressão grep afeta a saída

4

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 entendi porque as duas últimas tentativas de grep não estão retornando nenhum resultado.

    
por user3405291 03.05.2018 / 10:13

1 resposta

23

grep padrões são expressões regulares (também conhecidas como regex, regexp, RE), expressões regulares básicas (BRE), a menos que -E / -F / -P / -K / -X opção (apenas os dois primeiros sendo padrão) é usado.

* é 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 os operadores ^ ou \( regexp, ele corresponde a um literal * apenas (ele também é considerado literalmente dentro de [...] expressões de colchetes).

Portanto, grep '*README.md*' corresponde a linhas que contêm um literal * 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 (o que seria mostrado com% co_de) % opção do GNU --color por exemplo)).

Por exemplo, corresponderia a essas duas linhas:

*README mike
^^^^^^^^^
DONT***README-mddd
      ^^^^^^^^^^^^

(o grep s mostrando o que dentro da linha é correspondido pela expressão regular, que você pode ver com ^ )

Aqui, parece que você está confundindo expressões regulares com padrões de caractere curinga de shell. O operador de curinga --color que corresponde a 0 ou mais caracteres pode ser escrito * em expressões regulares. Mas fazendo:

grep '.*README\.md.*'

seria novamente o mesmo que:

grep 'README\.md'

Como .* procura uma correspondência dentro da linha, em vez de encontrar linhas que correspondam exatamente ao padrão (para o qual você precisa de grep ).

Com ast-open -x , que também é grep 'co_de% builtin (nem sempre interno por padrão, e você precisa habilitá-lo colocando ksh93 à frente de grep ), você pode usar a opção /opt/ast/bin para $PATH para usar curingas de shell (os ksh93 estendidos). Então, com essa implementação -K , você pode fazer:

grep -K 'README.md'

ou

grep -xK '*README.md*'

para corresponder às linhas que contêm grep .

Com essa mesma implementação, a correspondência de curingas também pode ser ativada em expressões regulares estendidas ( grep ), aumentadas README.md ) ou semelhantes a perl ( -E ) com -X operator (e -P em expressões regulares básicas que na verdade quebram a conformidade com POSIX, então eu não confiaria nele como poderia ser removido em uma versão futura). Então você pode fazer:

grep -xE '(?K)*README.md*'

lá.

Com qualquer implementação moderna de (?K) , você também pode fazer:

grep -F README.md

Para uma pesquisa de sequência fixa (em que \(?K\) acima corresponde a um literal grep em vez de qualquer caractere).

    
por 03.05.2018 / 10:24