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.
sumber
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.Tautan ini menjelaskan tentang bash Quotes and Escaping
Pertanyaan Anda berkaitan dengan tiga bagian pertama.
Di bawah ini adalah bagan tentang bagaimana string yang
bash
diteruskan ke merekagrep
dan seberapagrep
jauh menafsirkannya secara internal.Mari kita lihat dulu
echo "#ab\\cd" > file
.Dalam tanda kutip yang lemah ("")
"#ab\\cd"
,\\
ini adalah pelarian\
yang diteruskanfile
sebagai satu literal\
. Jadi,file
berisiab\cd
Sekarang, untuk perintah Anda: Grafik di bawah ini dapat membantu untuk melihat apa yang sebenarnya terjadi dengan setiap panggilan. The
*
menunjukkan orang-orang yang sesuai dengan isi file. Ini benar-benar hanya masalah menerapkan aturan melarikan diri bash, seperti pada halaman web, dengan catatan khusus untuk jawaban daniel kullmann di mana ia merujuk pada melarikan diri dari perilaku dalam situasi mengutip yang lemah .sumber