Bagaimana cara [br] ekspresi braket ricky ini bekerja?

38

Saya melihat one-liner ini baru-baru ini:

$ ps -ef | grep [f]irefox 

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

Jadi sepertinya mengembalikan daftar proses dengan "firefox" dalam data tetapi meninggalkan proses grep itu sendiri, dan karena itu tampaknya setara dengan:

ps -ef |grep -v grep| grep firefox

Saya tidak mengerti bagaimana cara kerjanya. Saya telah melihat halaman manual grep dan di tempat lain tetapi belum menemukan penjelasan.

Dan untuk menambah misteri jika saya lari:

$ 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] tampaknya berhenti bekerja!

Seseorang di sini akan tahu apa yang terjadi, saya yakin.

Terima kasih.

Thorsen
sumber
Hmm, apakah Anda yakin ini benar? ps -eaf | grep [fF] irefox akan lebih masuk akal. Ini terlihat seperti ekspresi reguler dan berarti cocok dengan salah satu karakter terlampir. Dapat dilakukan juga sebagai rentang, misalnya [0-9]
mbs
Baiklah. Itulah masalah yang saya alami: kelas karakter yang hanya berisi satu karakter tampak tidak ada artinya namun menghasilkan efek samping "misterius"! Pokoknya jokerdino telah memberikan penjelasan yang bagus.
Thorsen

Jawaban:

57

Ekspresi kurung siku adalah bagian dari bash shell (dan cangkang lain juga) pencocokan pola kelas karakter grep.

The grepProgram secara default mengerti POSIX ekspresi reguler dasar. Dengan itu Anda dapat mendefinisikan kelas karakter. Sebagai contoh ps -ef | grep [ab9]irefoxakan menemukan " a irefox", " b irefox", " 9 irefox" jika ada, tetapi bukan " ab irefox".

Perintah grep [a-zA-Z0-9]irefoxitu bahkan akan menemukan semua proses yang dimulai dengan tepat satu huruf atau angka dan diakhiri dengan "irefox".

Jadi ps -ef | grep firefoxmencari baris dengan firefoxdi dalamnya. Karena proses grep itu sendiri memiliki "firefox" di dalamnya, grep menemukan itu juga. Dengan menambahkan a[] , kita hanya mencari kelas karakter "[f]" (yang hanya terdiri dari huruf "f" dan karenanya setara dengan hanya "f" tanpa tanda kurung). Keuntungan dari tanda kurung sekarang adalah bahwa string "firefox" tidak lagi muncul dalam perintah grep. Karenanya, grep itu sendiri tidak akan muncul dalam hasil grep.

Karena tidak banyak orang yang akrab dengan tanda kurung siku sebagai pencocokan kelas karakter dan ekspresi reguler pada umumnya, hasil kedua mungkin terlihat sedikit misterius.

Jika Anda ingin memperbaiki hasil kedua, Anda dapat menggunakannya dengan cara ini:

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

(Referensi)

jokerdino
sumber
1
Hmm. Tidak terpikir oleh saya bahwa [] adalah sesuatu yang ditafsirkan oleh shell SEBELUM grep bahkan akan mendapatkan kesempatan. Terima kasih untuk penjelasannya. Semua [m] baterai diselesaikan.
Thorsen
Saya senang bisa membantu. Semoga harimu menyenangkan :)
jokerdino
1
Dalam bash, tanda kurung siku akan diteruskan ke grep jika tidak ada kecocokan untuk kata mereka (yaitu tidak ada file bernama "firefox" di direktori saat ini). Namun, grep juga memiliki kelas karakter dan [f] dalam grep sama dengan f.
Daniel Hershcovich
6
Sebenarnya dalam hal ini saya tidak berpikir itu ditafsirkan oleh shell sebelum grep. Saya pikir [f]adalah braket pencocokan pola ekspresi reguler untuk kelas karakter. Seperti pada "[a-z0-9] irefox" grep akan cocok dengan "airefox" dan "0irefox" juga. Anda dapat dengan mudah melihat bahwa itu bukan bash bawaan karena echo $([f])mengembalikan kesalahan.
con-f-use
4
Alasan spesifik yang [f]irefoxberfungsi untuk tujuan ini adalah tidak diperluas oleh shell. Ketika shell mengembang [f]irefoxke firefox, itu menyebabkan grepuntuk melihat firefox, dan kemudian firefoxadalah bagian dari grepstring perintah, persis seperti jika grep firefoxdijalankan. Tapi ada baiknya untuk mengingat pola shell yang cocok , terutama ketika scripting, karena jika ada file yang disebut firefoxdi direktori saat ini , maka shell tidak memperluas [f]irefoxkefirefox dan metode ini gagal, yaitu, grepgaris dari psditampilkan.
Eliah Kagan
10

Alasannya adalah karena string

grep firefox

cocok dengan polanya firefox, tetapi senarnya

grep [f]irefox

tidak cocok dengan polanya [f]irefox(yang setara dengan polanya firefox).

Itu sebabnya grep pertama cocok dengan baris perintah prosesnya sendiri, sedangkan grep pertama tidak.

Daniel Hershcovich
sumber
Ini membuat kepalaku semakin sakit
Pithikos