Confusão com o uso do grep com *?

1

Recentemente, conversei com um colega de trabalho enquanto ele estava em sua concha, quando o vi fazendo algo como ls -l | grep asdf* .

"Por que o glob?" Eu perguntei a ele. "É assim que sempre faço", ele respondeu.

Eu não vi nenhum problema imediatamente, mas ainda assim parecia errado. Quando tentei mais tarde, vi comportamentos diferentes:

--> ls -l | grep ls
-rwxr-xr-x 1 root root   22896 Nov 19  2012 false
-rwxr-xr-x 1 root root  105840 Nov 19  2012 ls
-rwxr-xr-x 1 root root   44640 Nov 19  2012 lsblk
-rwxr-xr-x 1 root root    6272 Nov 19  2012 lsmod
-rwxr-xr-x 1 root root   31912 Nov 19  2012 ntfsls

--> ls -l | grep ls*
Binary file lsblk matches
Binary file lsmod matches

O que está acontecendo aqui? Eu percebi que, na pior das hipóteses, o grep o trataria como regex l(s*) e me daria todas as ocorrências de l , mas essa entrada nem aparece no ls! (Estou executando isso de /bin ).

O que o grep faz quando você coloca um glob após sua string de pesquisa? Devo dizer ao meu colega de trabalho que pare de fazer isso no futuro?

    
por scohe001 07.08.2017 / 18:53

2 respostas

4

Quando você faz grep ls* , o shell primeiro expande ls* para uma lista de arquivos correspondentes no diretório atual, então o comando se torna

ls -l | grep ls lsblk lsmod

Nesse caso, grep ignorará a entrada padrão e tratará o primeiro argumento ls como um padrão a ser correspondido dentro dos arquivos lsblk e lsmod , como se você digitado grep ls lsblk lsmod (presumivelmente em /bin ):

$ grep ls lsblk lsmod
Binary file lsblk matches
Binary file lsmod matches

Por outro lado, se não houver correspondências glob no diretório atual e a opção nullglob do shell não estiver definida, então ls* será deixado un expandido, de modo que grepls* e corresponde a qualquer arquivo nomes correspondendo l seguido por zero ou mais s caracteres (basicamente qualquer nome de arquivo com l ) eg:

$ pwd
/home/steeldriver
$ echo ls*
ls*

(não há arquivos correspondentes ao shell glob ls* no meu diretório pessoal); então

$ ls /bin | grep 'ls*'
bzless
chacl
false
.
.
.
zless

tl; dr não faça isso

    
por steeldriver 07.08.2017 / 18:59
3

Para ser mais seguro, seu colega de trabalho deve usar:

ls -l | grep "asdf*"

para processar a saída canalizada, usando aspas estamos pulando as expansões de arquivo do shell, então estamos dizendo que procure por linhas com asd seguidas por zero ou mais f , um caso de uso melhor é:

ls -l | grep "asdf.*"

A outra coisa a ser mencionada é que, se não houver nenhum arquivo no diretório atual correspondente ao padrão, ele será considerado como é grep , na maioria das vezes é isso que acontece.

Observe também que analisar ls output não é bom .

    
por Ravexina 07.08.2017 / 19:03