*
memiliki makna khusus baik sebagai karakter shell globbing ("wildcard") dan sebagai metacharacter ekspresi reguler . Anda harus memperhitungkan keduanya, meskipun jika Anda mengutip ekspresi reguler Anda, maka Anda dapat mencegah shell memperlakukannya secara khusus dan memastikannya tidak berubah grep
. Meskipun agak mirip secara konseptual, apa *
artinya shell sangat berbeda dari apa artinya grep
.
Pertama , shell memperlakukan *
sebagai wildcard.
Kamu berkata:
Apakah ungkapan itu terlampir dalam tanda kutip tidak ada bedanya.
Itu tergantung pada file apa yang ada di direktori apa pun Anda berada ketika Anda menjalankan perintah. Untuk pola yang mengandung pemisah direktori /
, itu mungkin tergantung pada file apa yang ada di seluruh sistem Anda. Anda harus selalu mengutip ekspresi reguler untuk grep
- dan tanda kutip tunggal biasanya yang terbaik - kecuali jika Anda yakin Anda baik-baik saja dengan sembilan jenis transformasi yang berpotensi mengejutkan yang dilakukan shell sebelum menjalankan grep
perintah.
Ketika shell menemukan *
karakter yang tidak dikutip , itu berarti "nol atau lebih dari karakter apa pun" dan menggantikan kata yang mengandungnya dengan daftar nama file yang cocok dengan pola. (Nama file yang diawali dengan .
dikecualikan - kecuali pola Anda sendiri dimulai dengan .
atau Anda sudah mengkonfigurasi shell Anda untuk memasukkannya.) Ini dikenal sebagai globbing - dan juga dengan nama ekspansi nama file dan ekspansi nama path .
Efek dengan grep
biasanya adalah bahwa nama file yang cocok pertama diambil sebagai ekspresi reguler - bahkan jika itu akan sangat jelas bagi pembaca manusia bahwa itu tidak dimaksudkan sebagai ekspresi reguler - sementara semua nama file lain terdaftar secara otomatis dari Anda Glob diambil sebagai file di dalamnya untuk mencari kecocokan. (Anda tidak melihat daftar - itu diteruskan dengan tidak jelas ke grep
.) Anda hampir tidak pernah ingin ini terjadi.
Alasan mengapa hal ini terkadang bukan masalah - dan dalam kasus khusus Anda, setidaknya sejauh ini tidak - adalah yang *
akan dibiarkan jika semua hal berikut ini benar :
Tidak ada file yang namanya cocok. ... Atau Anda telah menonaktifkan globbing di shell Anda, biasanya dengan set -f
atau yang setara set -o noglob
. Tapi ini tidak biasa dan Anda mungkin tahu Anda melakukannya.
Anda menggunakan shell yang perilaku defaultnya dibiarkan begitu *
saja ketika tidak ada nama file yang cocok. Ini adalah kasus di Bash, yang mungkin Anda gunakan, tetapi tidak di semua kerang Bourne-style. (Perilaku default di shell populer Zsh, misalnya, adalah untuk gumpalan untuk (a) memperluas atau (b) menghasilkan kesalahan.) ... Atau Anda telah mengubah perilaku shell Anda - bagaimana yang dilakukan bervariasi lintas kerang.
Anda belum dinyatakan kepada shell Anda untuk memungkinkan gumpalan untuk diganti dengan apa-apa jika tidak ada file yang cocok, atau gagal dengan pesan kesalahan dalam situasi ini. Di Bash yang akan dilakukan dengan mengaktifkan opsi nullglob
atau failglob
shell , masing-masing.
Anda terkadang dapat mengandalkan # 2 dan # 3 tetapi Anda jarang dapat mengandalkan # 1. Sebuah grep
perintah dengan pola kuotasi yang bekerja sekarang mungkin berhenti bekerja ketika Anda memiliki file yang berbeda atau ketika Anda menjalankannya dari tempat yang berbeda. Mengutip ekspresi reguler Anda dan masalahnya hilang.
Kemudian pada grep
perintah memperlakukan *
sebagai quantifier a.
Jawaban lain - seperti yang oleh Sergiy Kolodyazhnyy dan oleh kos - juga mengatasi aspek pertanyaan ini, dengan cara yang agak berbeda. Jadi saya mendorong mereka yang belum membacanya untuk melakukannya, baik sebelum atau sesudah membaca sisa jawaban ini.
Dengan asumsi *
memang membuatnya untuk grep - yang mengutip harus memastikan - grep
kemudian berarti bahwa item yang mendahuluinya dapat terjadi beberapa kali , daripada harus terjadi tepat sekali . Itu masih bisa terjadi sekali. Atau mungkin tidak ada sama sekali. Atau bisa diulang. Teks yang cocok dengan segala kemungkinan itu akan dicocokkan.
Apa yang saya maksud dengan "item"?
Satu karakter . Sejak b
pertandingan literal sebuah b
, b*
cocok dengan nol atau lebih b
s, sehingga ab*c
cocok ac
, abc
, abbc
, abbbc
, dll
Demikian pula, karena .
pertandingan karakter apapun , .*
cocok dengan nol atau lebih karakter 1 , sehingga a.*c
pertandingan ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, bahkan acccccchjckhcc
, dll Atau
Kelas karakter . Sejak [xy]
pertandingan x
atau y
, [xy]*
pertandingan nol atau lebih karakter di mana masing-masing adalah baik x
atau y
, sehingga p[xy]*q
cocok pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
, dll
Ini juga berlaku untuk singkatan bentuk dari kelas karakter seperti \w
, \W
, \s
, dan \S
. Karena \w
cocok dengan karakter kata apa pun, \w*
cocok dengan nol atau lebih karakter kata. Atau
Sebuah kelompok . Sejak \(bar\)
pertandingan bar
, \(bar\)*
pertandingan nol atau lebih bar
s, sehingga foo\(bar\)*baz
cocok foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
, dll
Dengan opsi -E
atau -P
, masing-masing grep
memperlakukan ekspresi reguler Anda sebagai ERE atau PCRE , bukan sebagai BRE , dan kemudian grup dikelilingi oleh (
)
alih-alih \(
\)
, jadi Anda akan menggunakan (bar)
alih- alih \(bar\)
dan foo(bar)baz
sebagai ganti foo\(bar\)baz
.
man grep
memberikan penjelasan yang cukup dapat diakses tentang sintaks BRE dan ERE di bagian akhir, serta daftar semua opsi baris perintah yang grep
diterima di awal. Saya merekomendasikan halaman manual sebagai sumber daya, dan juga dokumentasi GNU Grep dan situs tutorial / referensi ini (yang saya tautkan ke sejumlah halaman, di atas).
Untuk pengujian dan pembelajaran grep
, saya sarankan memanggilnya dengan pola tetapi tanpa nama file. Kemudian dibutuhkan input dari terminal Anda. Masukkan garis; baris yang digemakan kembali kepada Anda adalah orang-orang yang berisi teks yang cocok dengan pola Anda. Untuk keluar, tekan Ctrl+ Ddi awal baris, yang menandakan akhir input. (Atau Anda dapat menekan Ctrl+ Cseperti kebanyakan program baris perintah). Misalnya:
grep 'This.*String'
Jika Anda menggunakan --color
bendera, grep
akan menyorot bagian- bagian spesifik dari garis Anda yang cocok dengan ekspresi reguler Anda, yang sangat berguna untuk menentukan apa yang dilakukan ekspresi reguler dan untuk menemukan apa yang Anda cari setelah Anda melakukannya. Secara default, pengguna Ubuntu memiliki alias Bash yang menyebabkan grep --color=auto
menjalankan - yang cukup untuk tujuan ini - ketika Anda menjalankan grep
dari baris perintah, sehingga Anda bahkan mungkin tidak perlu untuk lulus --color
secara manual.
1 Oleh karena itu, .*
dalam ekspresi reguler berarti apa *
artinya di dalam shell glob. Namun, perbedaannya adalah bahwa grep
secara otomatis mencetak garis yang berisi kecocokan Anda di mana saja di dalamnya, sehingga biasanya tidak perlu ada .*
di awal atau akhir ekspresi reguler.
* != any number of unknown characters