The echo
perintah tidak termasuk teks lengkap yang saya berikan. Misalnya, jika saya lakukan:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
Ini menghasilkan:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
Kutipan tunggal ( '
) yang saya miliki di perintah gema saya tidak termasuk. Jika saya beralih ke tanda kutip ganda:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
tidak menghasilkan apa-apa sama sekali! Mengapa itu meninggalkan tanda kutip tunggal dalam contoh pertama dan tidak menghasilkan apa-apa dalam yang kedua? Bagaimana cara mendapatkannya untuk menghasilkan apa yang saya ketikkan?
Jawaban:
Shell Anda menafsirkan kutipan, baik
'
dan"
, bahkan sebelum mereka sampaiecho
. Saya biasanya hanya menempatkan tanda kutip ganda di sekitar argumen saya untuk bergema bahkan jika mereka tidak perlu; sebagai contoh:Jadi, dalam contoh pertama Anda, jika Anda ingin menyertakan tanda kutip literal dalam output Anda, mereka juga harus diloloskan:
Atau mereka harus digunakan dalam argumen yang sudah dikutip (tetapi itu tidak bisa menjadi jenis kutipan yang sama, atau Anda akan perlu menghindarinya):
Dalam contoh kedua, Anda menjalankan substitusi perintah di tengah-tengah string:
Hal-hal yang mulai dengan
$
juga ditangani secara khusus oleh shell - itu memperlakukan mereka sebagai variabel dan menggantinya dengan nilai-nilai mereka. Karena kemungkinan besar variabel-variabel tersebut tidak diatur dalam shell Anda, sebenarnya hanya berjalanKarena
grep
hanya melihat satu argumen, diasumsikan bahwa argumen adalah pola yang Anda cari, dan bahwa tempat itu seharusnya membaca data adalah stdin, sehingga memblokir menunggu input. Itu sebabnya perintah kedua Anda tampaknya hang.Ini tidak akan terjadi jika Anda mengutip argumen tersebut (itulah sebabnya contoh pertama Anda hampir berhasil), jadi ini adalah salah satu cara untuk mendapatkan hasil yang Anda inginkan:
Anda juga dapat mengutip dua kali, tetapi Anda harus keluar dari
$
s sehingga shell tidak menyelesaikannya sebagai variabel, dan backticks agar shell tidak segera menjalankan substitusi perintah:sumber
Saya tidak akan menjelaskan lebih jauh mengapa usaha Anda berperilaku seperti itu, karena jawaban Michael Mrozek mencakup hal ini dengan baik. Singkatnya, segala sesuatu di antara tanda kutip tunggal (
'…'
) ditafsirkan secara harfiah (dan khususnya yang pertama'
menandai akhir dari string literal), sedangkan`
dan$
mempertahankan makna khusus mereka di antara"…"
.Tidak ada kutipan di dalam tanda kutip tunggal, jadi Anda tidak dapat menempatkan kutipan tunggal di dalam string yang dikutip tunggal. Namun ada ungkapan yang mirip:
Ini mencetak
foo'bar
, karena argumen untukecho
dibuat dari string tiga karakter yang dikutip tunggalfoo
, digabungkan dengan karakter tunggal'
(diperoleh dengan melindungi karakter'
dari makna khusus melalui pendahulunya\
), digabungkan dengan string tiga karakter yang dikutip tunggalbar
. Jadi, meskipun itu bukan yang terjadi di balik layar, Anda dapat menganggapnya'\''
sebagai cara untuk memasukkan satu kutipan di dalam string yang dikutip tunggal.Jika Anda ingin mencetak string multiline yang kompleks, alat yang lebih baik adalah dokumen di sini . Dokumen di sini terdiri dari dua karakter yang
<<
diikuti oleh penanda seperti<<EOF
, kemudian beberapa baris teks, kemudian penanda akhir sendiri pada barisnya. Jika marker dikutip dengan cara apa pun ('EOF'
atau"EOF"
atau\EOF
"E" "OF 'atau ...), maka teks diartikan secara harfiah (seperti di dalam tanda kutip tunggal, kecuali bahwa itu'
adalah karakter biasa). Jika penanda tidak dikutip sama sekali, maka teks ditafsirkan seperti dalam string yang dikutip ganda, dengan$\`
mempertahankan status khusus mereka (tetapi"
dan baris baru ditafsirkan secara harfiah).sumber
Oke, ini akan berhasil: -
Mengujinya di sini: -
sumber
Saran Gilles untuk menggunakan dokumen di sini sangat bagus, dan bahkan berfungsi dalam bahasa scripting seperti Perl. Sebagai contoh spesifik berdasarkan jawabannya pada masalah OP,
Memang, contoh ini sedikit dibuat-buat, tetapi saya telah menemukan itu menjadi teknik yang berguna untuk, katakanlah, mengirim pernyataan SQL ke
psql
(bukancat
).(Perhatikan bahwa karakter non-spasi non-alfanumerik dapat digunakan sebagai pengganti
#
konstruk kutipan generik di atas, tetapi hash tampak menonjol dengan baik untuk contoh ini, dan tidak diperlakukan sebagai komentar.)sumber
Ayo ambil perintahmu
dan pertama membaginya menjadi kata-kata, menggunakan spasi kosong sebagai tanda pembatas:
Selanjutnya, kita melakukan ekspansi parameter: perluas
$…
tetapi tidak di dalam'…'
. Karena$2
kosong (kecuali jika Anda mengaturnya melalui mis.set -- …
), Itu akan diganti oleh string kosong.Selanjutnya, lakukan penghapusan kutipan.
Argumen-argumen ini kemudian diteruskan ke echo, yang akan mencetak satu demi satu, dipisahkan oleh satu spasi.
Saya harap instruksi selangkah demi selangkah ini membuat perilaku yang diamati menjadi lebih jelas. Untuk menghindari masalah ini, keluar dari tanda kutip tunggal seperti ini:
Ini akan mengakhiri string yang dikutip tunggal, kemudian menambahkan kutipan tunggal (lolos) ke kata, kemudian memulai string kutipan tunggal baru, semua tanpa memecah kata.
sumber