Como esta expressão de [t] colchete irregular no grep funciona?

38

Eu vi esse verso recentemente:

$ ps -ef | grep [f]irefox 

thorsen   16730     1  1 Jun19 ?        00:27:27 /usr/lib/firefox/firefox ...

Portanto, parece retornar a lista de processos com "firefox" nos dados, mas deixando de fora o próprio processo grep e, portanto, parece aproximadamente equivalente a:

ps -ef |grep -v grep| grep firefox

Eu não consigo entender como isso funciona. Eu olhei a página de manual no grep e em outros lugares, mas não encontrei uma explicação.

E para agravar o mistério, se eu correr:

$ ps -ef | grep firefox  > data
$ grep [f]irefox data

thorsen   15820 28618  0 07:28 pts/1    00:00:00 grep --color=auto firefox
thorsen   16730     1  1 Jun19 ?        00:27:45 /usr/lib/firefox/firefox ....

o [t] rick parece parar de funcionar!

Alguém aqui saberá o que está acontecendo, tenho certeza.

Obrigado.

Thorsen
fonte
Hmm, você tem certeza de que isso está correto? ps -eaf | grep [fF] O irefox faria mais sentido. Parece uma expressão regular e significa que corresponde a qualquer um dos caracteres incluídos. Pode ser feito também como intervalo, por exemplo, [0-9]
mbs
Bem, sim. Esse era o problema que eu estava tendo: uma classe de personagem contendo apenas um personagem parecia inútil, mas estava produzindo um efeito colateral "misterioso"! De qualquer forma, o jokerdino forneceu uma boa explicação.
Thorsen

Respostas:

57

A expressão entre colchetes faz parte da correspondência do padrão bash shell (e outros shells) da classe de caracteres do grep.

O grepprograma, por padrão, compreende expressões regulares básicas do POSIX. Com isso você pode definir classes de caracteres. Por exemplo ps -ef | grep [ab9]irefox, localizaria " a irefox", " b irefox", " 9 irefox" se existissem, mas não " ab irefox".

O comando grep [a-zA-Z0-9]irefoxencontraria todos os processos que começam com exatamente uma letra ou número e terminam em "irefox".

Então, ps -ef | grep firefoxprocura por linhas com firefoxele. Como o próprio processo grep tem "firefox", o grep também o encontra. Ao adicionar a [], procuramos apenas a classe de caracteres "[f]" (que consiste apenas na letra "f" e, portanto, é equivalente a apenas um "f" sem os colchetes). A vantagem dos colchetes agora é que a string "firefox" não aparece mais no comando grep. Portanto, o grep em si não aparecerá no resultado do grep.

Como poucas pessoas estão familiarizadas com colchetes como correspondência de classe de caracteres e expressões regulares em geral, o segundo resultado pode parecer um pouco misterioso.

Se você deseja corrigir o segundo resultado, pode usá-los desta maneira:

ps -ef | grep [f]irefox  > data
grep firefox data

(Referência)

jokerdino
fonte
1
Hmm. Não me ocorreu que o [] era algo interpretado pelo shell ANTES do grep ter uma chance. Obrigada pelo esclarecimento. Todos os [m] yteries resolvidos.
Thorsen
Feliz por ajudar. Tenha um bom dia :)
jokerdino
1
No bash, os colchetes serão passados ​​para grep se não houver correspondência para a palavra em que estão (ou seja, nenhum arquivo chamado "firefox" no diretório atual). No entanto, o grep também possui classes de caracteres e [f] no grep é o mesmo que f.
Daniel Hershcovich
6
Na verdade, neste caso, não acho que seja interpretado pelo shell antes do grep. Eu acho que [f]é o suporte de correspondência de padrão de expressão regular para classes de caracteres. Como em "[a-z0-9] irefox", o grep também corresponderia a "airefox" e "0irefox". Você pode ver facilmente que não é um bash interno, pois echo $([f])retorna um erro.
con-f-use
4
O motivo específico [f]irefoxfunciona para esse fim é que ele não é expandido pelo shell. Quando o shell se expande [f]irefoxpara firefox, isso causa grepa visualização firefoxe firefoxfaz parte da grepsequência de comandos do comando, exatamente como se grep firefoxfosse executado. Mas é bom ter em mente a correspondência de padrões de shell , principalmente ao criar scripts, porque se houver um arquivo chamado firefoxno diretório atual , em seguida, o shell não expandir [f]irefoxparafirefox e este método falhar, ou seja, a greplinha de psé mostrado.
Eliah Kagan
10

O motivo é que a string

grep firefox

corresponde ao padrão firefox, mas a string

grep [f]irefox

não corresponde ao padrão [f]irefox(que é equivalente ao padrão firefox).

É por isso que o primeiro grep corresponde à sua própria linha de comando do processo, enquanto o segundo não.

Daniel Hershcovich
fonte
Isso faz minha cabeça doer ainda mais
Pithikos