Saya baru-baru ini mengalami masalah dengan beberapa regex pada command-line, dan menemukan bahwa untuk mencocokkan backslash, jumlah karakter yang berbeda dapat digunakan. Angka ini tergantung pada kutipan yang digunakan untuk regex (tidak ada, harga tunggal, harga ganda). Lihat sesi bash berikut untuk maksud saya:
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
Ini berarti:
- tanpa tanda kutip, saya dapat mencocokkan backslash dengan 4-7 backslash yang sebenarnya
- dengan tanda kutip ganda, saya dapat mencocokkan backslash dengan 3-6 backslash yang sebenarnya
- Dengan tanda kutip tunggal, saya dapat mencocokkan backslash dengan 2-3 backslash yang sebenarnya
Saya mengerti bahwa satu backslash tambahan diabaikan oleh shell (dari halaman bash man):
"Backslash (\) yang tidak dikutip adalah karakter pelarian. Ini mempertahankan nilai literal dari karakter selanjutnya yang mengikuti"
Ini tidak berlaku untuk contoh yang dikutip tunggal, karena tidak ada pelarian yang dilakukan dalam kutipan tunggal.
Dan satu backslash tambahan diabaikan oleh perintah grep ("\ c" hanya "c" lolos, tetapi ini sama dengan "c", karena "c" tidak memiliki arti khusus dalam regex).
Ini menjelaskan perilaku contoh dengan tanda kutip tunggal, tapi saya tidak benar-benar memahami dua contoh lainnya, terutama mengapa ada perbedaan antara string tidak-dikutip dan string yang dikutip ganda.
Sekali lagi, kutipan dari halaman bash man:
"Menutup karakter dalam tanda kutip ganda mempertahankan nilai literal semua karakter dalam tanda kutip, dengan pengecualian $,`, \, dan, ketika ekspansi sejarah diaktifkan,! "
Saya mencoba hal yang sama dengan GNU awk (eg awk /ab\cd/{print} file), dengan hasil yang sama.
Perl, bagaimanapun, menunjukkan hasil yang berbeda (menggunakan misalnya perl -ne
"/ab\\cd/"\&\&print file):
- tanpa tanda kutip, saya dapat mencocokkan backslash dengan 4-5 backslash yang sebenarnya
- dengan tanda kutip ganda, saya dapat mencocokkan backslash dengan 3-4 backslash yang sebenarnya
- Dengan tanda kutip tunggal, saya dapat mencocokkan backslash dengan 2 backslash yang sebenarnya
Adakah yang bisa menjelaskan perbedaan antara string regex yang tidak dikutip dan double-qouted pada command-line untuk grep dan awk? Saya tidak begitu tertarik pada penjelasan tentang perilaku Perl, karena saya biasanya tidak menggunakan Perl satu kalimat.
printf "\ntest"akan menyisipkan baris baru sebelum "test", meskipun"\n"seharusnya telah diterjemahkan"n"oleh shell seperti halnya dua tanda kutip ganda ... (jadi hasil yang diharapkan seharusnya, untuk "\ ntest", "ntest". Kita harus memiliki kebiasaan untuk menulis:printf "\\ntest"atauprintf '\ntest', tetapi entah bagaimana saya melihat banyak naskah yang mengandalkan keanehan sebagai gantinya.