Jak działa to wyrażenie w nawiasach klamrowych w grep?

38

Ostatnio widziałem ten jednowarstwowy:

$ ps -ef | grep [f]irefox 

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

Wydaje się więc, że zwraca listę procesów z „firefox” w danych, ale pomija sam proces grep, a zatem wydaje się w przybliżeniu równoważny z:

ps -ef |grep -v grep| grep firefox

Nie rozumiem jednak, jak to działa. Przeglądałem stronę man na grep i gdzie indziej, ale nie znalazłem wyjaśnienia.

I pogłębić tajemnicę, jeśli uruchomię:

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

rick [t] wydaje się przestać działać!

Jestem pewien, że ktoś tu będzie wiedział, co się dzieje.

Dzięki.

Thorsen
źródło
Hmm, jesteś pewien, że to prawda? ps -eaf | grep [fF] irefox miałby więcej sensu. To wygląda jak wyrażenie regularne i oznacza pasujące do każdego z dołączonych znaków. Można to zrobić również jako zakres, np. [0-9]
mbs
No tak. Taki był mój problem: klasa postaci zawierająca tylko jedną postać wydawała się bezcelowa, a jednak wywoływała „tajemniczy” efekt uboczny! W każdym razie jokerdino dostarczyło dobre wyjaśnienie.
Thorsen

Odpowiedzi:

57

Wyrażenie w nawiasach kwadratowych jest częścią powłoki bash (i również innych powłok) dopasowywania wzorców klas znaków grep.

grepProgram domyślnie rozumie podstawowych wyrażeń regularnych POSIX. Dzięki temu możesz zdefiniować klasy postaci. Na przykład ps -ef | grep [ab9]irefoxznajdzie " na irefox", " b irefox", " 9 irefox" jeśli te istniały, ale nie " ab irefox".

Polecenie grep [a-zA-Z0-9]irefoxznajdzie nawet wszystkie procesy, które zaczynają się dokładnie jedną literą lub cyfrą i kończą na „irefox”.

Więc ps -ef | grep firefoxszuka linii firefoxw nim. Ponieważ sam proces grep zawiera „firefox”, grep również to znajduje. Dodając „a” [], szukamy tylko klasy znaków „[f]” (która składa się tylko z litery „f” i dlatego jest odpowiednikiem tylko „f” bez nawiasów). Zaletą nawiasów jest to, że ciąg „firefox” nie pojawia się już w poleceniu grep. Dlatego samo grep nie pojawi się w wyniku grep.

Ponieważ niewiele osób zna nawiasy kwadratowe jako dopasowanie klas znaków i wyrażenia regularne w ogóle, drugi wynik może wyglądać nieco tajemniczo.

Jeśli chcesz naprawić drugi wynik, możesz użyć ich w ten sposób:

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

(Odniesienie)

jokerdino
źródło
1
Hmm Nie przyszło mi do głowy, że [] było czymś interpretowanym przez powłokę, ZANIM grep nawet miał szansę. Dziękuję za wyjaśnienie. Wszystkie [m] akumulatory zostały rozwiązane.
Thorsen
Chętnie pomoże. Miłego dnia :)
jokerdino
1
W bash nawiasy kwadratowe będą przekazywane do grep, jeśli nie ma dopasowania do słowa, w którym się znajdują (tzn. Nie ma pliku o nazwie „firefox” w bieżącym katalogu). Jednak grep ma również klasy znaków, a [f] w grep jest tak samo jak f.
Daniel Hershcovich
6
Właściwie w tym przypadku nie sądzę, aby była interpretowana przez powłokę przed grep. Myślę, że [f]to nawias dopasowujący wzorce wyrażeń regularnych dla klas znaków. Jak w „[a-z0-9] irefox” grep pasowałby również do „airefox” i „0irefox”. Możesz łatwo zobaczyć, że nie jest to wbudowana bash, ponieważ echo $([f])zwraca błąd.
con-f-use
4
Konkretnym powodem [f]irefoxtego działania jest to, że nie jest on rozszerzany przez powłokę. Gdy powłoka rozwija się [f]irefoxdo firefox, powoduje grepto zobaczenie firefox, a następnie firefoxjest częścią grepciągu poleceń, dokładnie tak, jakby grep firefoxbyła uruchomiona. Ale dobrze jest zachować powłoki wzorzec dopasowania na uwadze , szczególnie gdy skryptowy, bo jeśli istnieje plik o nazwie firefoxw bieżącym katalogu , następnie powłoka ma rozwijać [f]irefoxsięfirefox i ta metoda zawiedzie, czyli greplinię od pspokazano.
Eliah Kagan
10

Powodem jest to, że ciąg

grep firefox

pasuje do wzoru firefox, ale ciąg

grep [f]irefox

nie pasuje do wzorca [f]irefox(co jest równoważne wzorowi firefox).

Właśnie dlatego pierwszy grep odpowiada własnej linii poleceń procesu, a drugi nie.

Daniel Hershcovich
źródło
To jeszcze bardziej boli mnie w głowę
Pithikos