Dalam ekspresi reguler, karakter mana yang perlu diloloskan?

23

Secara umum, karakter mana dalam ekspresi reguler yang perlu diloloskan?

Misalnya, berikut ini tidak benar secara sintaksis:

echo '[]' | grep '[]'
grep: Unmatched [ or [^

Namun, ini secara sintaksis benar:

echo '[]' | grep '\[]'
[]

Apakah ada dokumentasi tentang karakter mana yang harus diloloskan dalam ekspresi reguler, dan yang tidak?

LanceBaynes
sumber

Jawaban:

12

Ini tergantung pada aplikasinya. Dalam contoh Anda [harus dikutip sebagai argumen untuk greptetapi tidak echo.

Untuk shell (dari spesifikasi POSIX ):

Mengutip digunakan untuk menghapus makna khusus karakter atau kata-kata tertentu ke shell. Mengutip dapat digunakan untuk mempertahankan makna literal dari karakter khusus dalam paragraf berikutnya, mencegah kata-kata yang dicadangkan untuk dikenali seperti itu, dan mencegah ekspansi parameter dan substitusi perintah dalam pemrosesan dokumen di sini (lihat Dokumen-Di sini).

Aplikasi harus mengutip karakter berikut jika mereka ingin mewakili diri mereka sendiri:

|  &  ;  <  >  (  )  $  `  \  "  '  <space>  <tab>  <newline>

dan berikut ini mungkin perlu dikutip dalam keadaan tertentu. Artinya, karakter-karakter ini mungkin istimewa tergantung pada kondisi yang dijelaskan di bagian lain dalam volume IEEE Std 1003.1-2001 ini:

*   ?   [   #   ˜   =   %

Berbagai mekanisme penawaran adalah karakter pelarian, tanda kutip tunggal, dan tanda kutip ganda. Dokumen di sini mewakili bentuk kutipan lainnya; lihat Di Sini-Dokumen.

Program spesifik (menggunakan regex, perl, awk) dapat memiliki persyaratan tambahan untuk melarikan diri.

Matteo
sumber
8

Setiap aplikasi akan memiliki set karakter 'khusus'. Masalah yang Anda temui adalah bersamagrep bukan dengan shell. Untuk karakter yang perlu dikutip grep, baca bagian manual di "EKSPRESI REGULER".

Untuk shell, karakter yang harus dikutip adalah:

;'"`#$&*?[]<>{}\

dan spasi putih.

Bergantung pada shell, karakter lain mungkin perlu dikutip juga:

!^%

Lihat di bawah "SHELL GRAMMAR" di halaman shell.

Arcege
sumber
Dalam beberapa shell dengan ekspansi sejarah ( bashtermasuk), !masih diperluas dalam tanda kutip ganda, hanya tanda kutip tunggal yang akan menghentikan ekspansi (atau mematikan opsi shell).
Chris Down
]seharusnya tidak dikutip, [tidak selalu. Saya tidak menemukan referensi ke {dan}
Matteo
8

Ada beberapa jenis ekspresi reguler dan himpunan karakter khusus bergantung pada jenis tertentu. Beberapa dari mereka dijelaskan di bawah ini. Dalam semua kasus, karakter khusus lolos dengan backslash \. Misalnya untuk mencocokkan [Anda menulis \[. Atau karakter (kecuali^ ) dapat melarikan diri dengan melampirkan mereka di antara tanda kurung satu per satu seperti [[].

Karakter yang spesial dalam beberapa konteks seperti ^ spesial pada awal (sub-) ekspresi dapat diloloskan dalam semua konteks.

Seperti orang lain menulis: di shell jika Anda tidak menyertakan ekspresi antara tanda kutip tunggal Anda harus melarikan diri karakter khusus untuk shell di regex yang sudah lolos. Contoh: Alih-alih '\['Anda dapat menulis \\[(atau: "\["atau "\\[") di shell Bourne yang kompatibel seperti bash tapi ini adalah cerita lain.

Basic Regular Expressions (BRE)

  • POSIX: Ekspresi Reguler Dasar
  • Perintah: grep,sed
  • Karakter spesial: .[\
  • Khusus dalam beberapa konteks: *^$
  • Kabur dari string: "$(printf '%s' "$string" | sed 's/[.[\*^$]/\\&/g')"

Extended Regular Expressions (ERE)

  • POSIX: Ekspresi Reguler Diperpanjang
  • Perintah:, grep -EGNU sed -r:, * BSD:sed -E
  • Karakter spesial: .[\(
  • Khusus dalam beberapa konteks: *^$)+?{|
  • Kabur dari string: "$(printf '%s' "$string" | sed 's/[.[\*^$()+?{|]/\\&/g')"
pabouk
sumber
3

grepmenggunakan BRE sebagai metode regex-nya. Ada dokumentasi yang baik pada itu di sini , ikhtisar umum akan "melarikan diri karakter khusus atau metakarakter untuk mendapatkan harfiahnya, melarikan diri untuk membuat escape sequence ( \n, \r, dll)", meskipun hal ini tidak selalu benar, misalnya, Anda harus melarikan diri (dan )mendapatkan makna khusus mereka (backreference).

Chris Down
sumber
0

Shell dapat mengubah baris perintah sebelum eksekusi perintah. Baik shell dan grepdapat menggunakan mengutip untuk menghapus arti khusus dari beberapa karakter. Meskipun demikian, grepdan kerang memiliki karakter khusus yang berbeda. Selain itu, karakter khusus yang tidak terhapuskan yang tidak dihasilkan dari ekspansi yang ada dihapus, sebelum eksekusi perintah, oleh shell.

echo '[]' | grep '[]'

Shell mentransmisikan argumen []ke grepdan diuraikan sebagai ekspresi braket salah oleh grep.

echo '[]' | grep \[]

Di atas, kita bisa melihat kasus serupa. Garis miring terbalik dihapus dan []dikirim sebagai argumen untuk grep. grepmengenali ekspresi braket yang salah.

echo '[]' | grep '\[]'

Akhirnya, dalam kasus ini, tanda kutip dihapus oleh shell dan \[]ditransmisikan sebagai argumen untuk greptetapi, dalam kasus khusus ini ¹, \[ditafsirkan grepsebagai braket literal. Kutipan diperlukan untuk mencegah interpretasi backslash sebagai karakter khusus oleh shell.


¹ Spesifikasi POSIX .

Fólkvangr
sumber