Come funziona questa [t] espressione di parentesi traballanti in grep?


38

Ho visto questo one-liner di recente:

$ ps -ef | grep [f]irefox 

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

Quindi sembra restituire l'elenco dei processi con "firefox" nei dati ma tralasciando il processo grep stesso, e quindi sembra approssimativamente equivalente a:

ps -ef |grep -v grep| grep firefox

Non riesco a capire come funzioni però. Ho guardato la pagina man su grep e altrove ma non ho trovato una spiegazione.

E per aggravare il mistero se corro:

$ 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 ....

il [t] rick sembra smettere di funzionare!

Qualcuno qui saprà cosa sta succedendo, ne sono sicuro.

Grazie.


Hmm, sei sicuro che sia corretto? ps -eaf | grep [fF] irefox avrebbe più senso. Questa sembra un'espressione regolare e in qualche modo corrisponde a uno qualsiasi dei caratteri racchiusi. Potrebbe essere eseguito anche come intervallo, ad esempio [0-9]
mbs

Beh si. Quello era il problema che stavo avendo: una classe di personaggi che conteneva un solo personaggio sembrava inutile, ma produceva un effetto "misterioso"! Comunque jokerdino ha fornito una buona spiegazione.
Thorsen,

Risposte:


57

L'espressione parentesi quadra fa parte della corrispondenza bash shell (e anche di altre shell) del modello di classe di caratteri di grep.

Il grepprogramma di default comprende le espressioni regolari di base POSIX. Con ciò puoi definire le classi di caratteri. Ad esempio ps -ef | grep [ab9]irefoxtroverebbe " a irefox", " b irefox", " 9 irefox" se esistessero, ma non " ab irefox".

Il comando grep [a-zA-Z0-9]irefoxtroverebbe anche tutti i processi che iniziano esattamente con una lettera o un numero e terminano in "irefox".

Quindi ps -ef | grep firefoxcerca le linee con firefoxdentro. Poiché il processo grep stesso contiene "firefox", anche grep lo trova. Aggiungendo a [], stiamo solo cercando la classe di caratteri "[f]" (che consiste solo della lettera "f" ed è quindi equivalente a una "f" senza parentesi). Il vantaggio delle parentesi ora è che la stringa "firefox" non appare più nel comando grep. Pertanto, grep stesso non verrà visualizzato nel risultato grep.

Poiché non molte persone hanno familiarità con le parentesi quadre come la corrispondenza della classe di caratteri e le espressioni regolari in generale, il secondo risultato potrebbe sembrare un po 'misterioso.

Se vuoi correggere il secondo risultato, puoi usarli in questo modo:

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

(Riferimento)


1
Hmm. Non mi è venuto in mente che il [] fosse qualcosa interpretato dalla shell PRIMA che grep potesse anche avere una possibilità. Grazie per la spiegazione. Tutti i [m] yterie sono stati risolti.
Thorsen,

Felice di aiutare. Buona giornata :)
jokerdino

1
In bash, le parentesi quadre verranno passate a grep se non c'è corrispondenza per la parola in cui si trovano (cioè nessun file chiamato "firefox" nella directory corrente). Tuttavia, grep ha anche classi di caratteri e [f] in grep è uguale a f.
Daniel Hershcovich,

6
In realtà in questo caso non credo sia interpretato dalla shell prima di grep. Penso che [f]sia la parentesi di corrispondenza del modello di espressione regolare per le classi di caratteri. Come in "[a-z0-9] irefox" grep corrisponderebbe anche a "airefox" e "0irefox". Si può facilmente vedere che non è un built-in bash poiché echo $([f])restituisce un errore.
con-f-use

4
Il motivo specifico [f]irefoxopere per questo scopo è che è non espanso dalla shell. Quando la shell si espande [f]irefoxin firefox, ciò fa grepvedere firefox, e quindi firefoxfa parte della grepstringa di comando, esattamente come se grep firefoxfosse eseguita. Ma è bene tenere pattern matching scocca in mente , soprattutto quando script, perché se c'è un file chiamato firefoxnella directory corrente , allora la shell non espandersi [f]irefoxafirefox e questo metodo non riesce, cioè, la greplinea da psè mostrato.
Eliah Kagan,

10

Il motivo è che la stringa

grep firefox

corrisponde al modello firefox, ma alla stringa

grep [f]irefox

non corrisponde al modello [f]irefox(che equivale al modello firefox).

Ecco perché il primo grep corrisponde alla sua riga di comando del processo, mentre il secondo no.


Questo mi fa ancora più male alla testa
Pithikos,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.