Saya memiliki file yang memiliki "lalu" dan "di sana".
saya bisa
$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some
dan saya bisa
$ grep "there " x.x
If there is no blob none some will be created
Bagaimana saya bisa mencari keduanya dalam satu operasi? Saya mencoba
$ grep (then|there) x.x
-bash: kesalahan sintaks dekat token yang tidak terduga `('
dan
grep "(then|there)" x.x
durrantm.../code
# (Nothing)
grep
regular-expression
Michael Durrant
sumber
sumber
Jawaban:
Anda harus memasukkan ekspresi dalam tanda kutip. Kesalahan yang Anda terima adalah hasil dari bash mengartikan
(
sebagai karakter khusus.Juga, Anda perlu memberi tahu grep untuk menggunakan ekspresi reguler yang diperluas.
Tanpa ekspresi reguler diperpanjang, Anda harus melarikan diri
|
,(
dan)
. Perhatikan bahwa kami menggunakan tanda kutip tunggal di sini. Bash memperlakukan backslash dalam tanda kutip ganda khusus.Pengelompokan tidak diperlukan dalam kasus ini.
Ini akan diperlukan untuk sesuatu seperti ini:
sumber
grep $'then\nthere'
dangrep -e then -e there
. Perhatikan bahwa\|
ini bukan standar dalam BRE. Sisanya adalah. Bash memperlakukan backslashes khusus dalam tanda kutip ganda hanya sebelum"
,$
,\
,`
dan baris baru.x.x
?Hanya tambahan cepat, sebagian besar rasa memiliki perintah yang disebut egrep yang hanya grep dengan -E. Saya pribadi suka mengetik yang lebih baik
Daripada menggunakan grep -E
sumber
Hal-hal yang didokumentasikan dalam EKSPRESI REGULER di halaman manual (atau setidaknya, saya) sebenarnya untuk regexps yang diperluas ;
Tetapi secara default grep tidak menggunakannya - Anda memerlukan
-E
sakelar:Karena (dari halaman manual lagi):
Jadi, Anda juga dapat menggunakan:
Karena tanda kurung berlebihan dalam kasus ini.
sumber
Kesederhanaan elegan Bash tampaknya hilang di halaman manualnya yang besar.
Selain solusi hebat di atas, saya pikir saya akan mencoba memberi Anda lembar contekan tentang bagaimana bash mem-parsing dan menginterpretasikan pernyataan . Kemudian dengan menggunakan peta jalan ini saya akan menguraikan contoh-contoh yang disajikan oleh penanya untuk membantu Anda lebih memahami mengapa mereka tidak berfungsi sebagaimana dimaksud.
Catatan: Baris skrip Shell digunakan secara langsung. Input-line yang diketik adalah histori pertama yang diperluas.
Setiap baris bash pertama-tama ditandai , atau dengan kata lain dipotong menjadi apa yang disebut token . (Tokenisasi terjadi sebelum semua ekspansi lainnya, termasuk penjepit, tilde, parameter, perintah, aritmatika, proses, pemisahan kata, & ekspansi nama file.)
Token di sini berarti bagian dari jalur input dipisahkan (dibatasi) oleh salah satu karakter meta khusus ini:
Bash menggunakan banyak karakter khusus lainnya tetapi hanya 10 yang menghasilkan token awal.
Namun karena meta-karakter ini juga terkadang harus digunakan dalam token, perlu ada cara untuk menghilangkan makna khusus mereka. Ini disebut melarikan diri. Lolos dilakukan baik dengan mengutip string dari satu atau lebih karakter, (yaitu
'xx..'
,"xx.."
), atau dengan mengawali karakter individu dengan garis miring, (yaitu\x
). (Ini sedikit lebih rumit dari ini karena tanda kutip juga perlu dikutip, dan karena tanda kutip ganda tidak mengutip semuanya, tetapi penyederhanaan ini akan berlaku untuk saat ini.)Jangan bingung mengutip bash dengan gagasan mengutip string teks, seperti dalam bahasa lain. Apa yang ada di antara tanda kutip di bash bukanlah string, melainkan bagian dari baris input yang memiliki meta-karakter yang lolos sehingga mereka tidak membatasi token.
Perhatikan, ada perbedaan penting antara
'
, dan"
, tapi itu untuk hari lain.Meta-karakter unescaped yang tersisa kemudian menjadi pemisah token.
Sebagai contoh,
Dalam contoh pertama ada dua token yang dihasilkan oleh pembatas ruang:
echo
danxyz
.Demikian juga pada contoh ke-2.
Pada contoh ketiga titik koma adalah melarikan diri, jadi ada 4 token yang dihasilkan oleh pembatas ruang,
echo
,x;
,echo
, dany
. Token pertama kemudian dijalankan sebagai perintah, dan mengambil tiga token berikutnya sebagai input. Catatan 2echo
tidak dieksekusi.Yang penting untuk diingat adalah bahwa penampilan pertama bash untuk karakter melarikan diri (
'
,"
, dan\
), dan kemudian mencari pembatas meta-karakter yang tidak lolos, dalam urutan itu.Jika tidak lolos maka 10 karakter khusus ini berfungsi sebagai
token
pembatas. Beberapa dari mereka juga memiliki makna tambahan, tetapi pertama dan terutama, mereka adalah pembatas token.Apa yang diharapkan grep
Dalam contoh di atas grep perlu token ini,
grep
,string
,filename
.Percobaan pertama adalah:
Dalam hal ini
(
,)
dan|
adalah meta karakter unescaped dan berfungsi untuk membagi masukan ke token ini:grep
,(
,then
,|
,there
,)
, danx.x
. grep ingin melihatgrep
,then|there
danx.x
.Percobaan kedua adalah:
Ini tokenizes ke
grep
,(then|there)
,x.x
. Anda dapat melihat ini jika Anda menukar grep dengan gema:sumber