@ jw013 Poin bagus dan artikel bagus. Saya suka kutipan "Variabel menyimpan data, fungsi menyimpan kode." dari tautan pertama, tetapi untuk penggunaan saya, data yang diberikan ke suatu fungsi (dalam hal ini, at) adalah kode. Adakah tips tentang cara yang lebih aman untuk mengatur / mengumpulkan kode yang akan diberikan at?
Cory Klein
atmengambil shsintaks sebagai input. Jadi menghasilkan input untuk atberarti menghasilkan shsintaks yang valid dan dikutip dengan benar dari input sewenang-wenang, yang tidak sepele, jadi saya akan mencoba menghindarinya jika memungkinkan. Akan sangat membantu jika Anda bisa memberikan sedikit lebih banyak detail tentang apa yang ingin Anda capai.
jw013
Maaf, saya tidak ingin mengalihkan perhatian dengan terlalu banyak detail, tetapi apa yang saya lakukan tidak terlalu rumit, IMO. Saya membuat skrip yang membutuhkan "waktu" dan "pesan". Itu kemudian berjalan atuntuk "waktu" yang diberikan, dan memberitahu atuntuk menjalankan perintah dzen2. dzen2mengambil "pesan" dari stdin, dan juga menggunakan beberapa parameter statis lainnya. Kesulitannya adalah saya perlu menyalurkan parameter "pesan" dari pengguna ke dzen2perintah, tapi saya tidak benar-benar menjalankan dzen2sendiri, saya mengatakan atuntuk melakukannya.
Penting juga untuk dicatat bahwa kutipan dievaluasi secara berbeda; tanda kutip ganda (") memungkinkan evaluasi string terlampir, tanda kutip tunggal (') mencetak string sebagai literal. Contoh: "$(ls)"dan '$(ls)'. Ini adalah alasan mengapa kutipan muncul dalam contoh pertanyaan asli.
Joseph Kern
Array juga merupakan sumber masalah. Kode milik fungsi, data ke variabel. Contoh yang Anda sajikan bekerja hanya karena tanda kutip dihapus dalam pemisahan array. A printf '<%s> ' "${VAR[@]}"akan menunjukkan bahwa kutipan sudah dihapus. Jika Anda menetapkan VAR sebagai VAR=(echo \"hi\")benar-benar memiliki tanda kutip, masalah yang sama muncul lagi, $ ${VAR[@]}akan dicetak"hi"
9
Penghapusan kutipan hanya terjadi pada kata-kata input asli, bukan pada hasil ekspansi. Kutipan yang merupakan bagian dari variabel yang diperluas tidak tersentuh.
Jika Anda mundur sedikit, Anda dapat melihat mengapa substitusi variabel benar-benar harus mempertahankan tanda kutip.
Inti dari kutipan dalam shell Unix / Linux / BSD adalah untuk menjaga potongan-potongan string bersama yang jika tidak akan diuraikan sebagai beberapa string. Karena secara default shell menggunakan spasi sebagai pemisah token, string dengan spasi (seperti "satu dua tiga") jika tidak dikutip atau lolos, akan diurai menjadi 3 string: "satu", "dua" dan "tiga".
Jika seorang programmer menginginkan sebuah string dengan nilai beberapa variabel diinterpolasi:
VAR=two
STRING="one $VAR three"
shell harus benar-benar tidak menghapus tanda kutip: string yang berisi spasi akan diuraikan sebagai 3 string yang lebih kecil.
eval
merupakan ladang ranjau dari lubang keamanan potensial yang harus Anda tapak dengan hatiat
) adalah kode. Adakah tips tentang cara yang lebih aman untuk mengatur / mengumpulkan kode yang akan diberikanat
?at
mengambilsh
sintaks sebagai input. Jadi menghasilkan input untukat
berarti menghasilkansh
sintaks yang valid dan dikutip dengan benar dari input sewenang-wenang, yang tidak sepele, jadi saya akan mencoba menghindarinya jika memungkinkan. Akan sangat membantu jika Anda bisa memberikan sedikit lebih banyak detail tentang apa yang ingin Anda capai.at
untuk "waktu" yang diberikan, dan memberitahuat
untuk menjalankan perintahdzen2
.dzen2
mengambil "pesan" dari stdin, dan juga menggunakan beberapa parameter statis lainnya. Kesulitannya adalah saya perlu menyalurkan parameter "pesan" dari pengguna kedzen2
perintah, tapi saya tidak benar-benar menjalankandzen2
sendiri, saya mengatakanat
untuk melakukannya.Jawaban:
Pasangan penawaran tambahan hanya akan dikonsumsi oleh langkah evaluasi tambahan. Misalnya dipaksa oleh
eval
:Tetapi umumnya adalah ide yang buruk untuk menempatkan perintah dengan parameter dalam satu string. Gunakan array sebagai gantinya:
sumber
"$(ls)"
dan'$(ls)'
. Ini adalah alasan mengapa kutipan muncul dalam contoh pertanyaan asli.printf '<%s> ' "${VAR[@]}"
akan menunjukkan bahwa kutipan sudah dihapus. Jika Anda menetapkan VAR sebagaiVAR=(echo \"hi\")
benar-benar memiliki tanda kutip, masalah yang sama muncul lagi,$ ${VAR[@]}
akan dicetak"hi"
Penghapusan kutipan hanya terjadi pada kata-kata input asli, bukan pada hasil ekspansi. Kutipan yang merupakan bagian dari variabel yang diperluas tidak tersentuh.
sumber
Jika Anda mundur sedikit, Anda dapat melihat mengapa substitusi variabel benar-benar harus mempertahankan tanda kutip.
Inti dari kutipan dalam shell Unix / Linux / BSD adalah untuk menjaga potongan-potongan string bersama yang jika tidak akan diuraikan sebagai beberapa string. Karena secara default shell menggunakan spasi sebagai pemisah token, string dengan spasi (seperti "satu dua tiga") jika tidak dikutip atau lolos, akan diurai menjadi 3 string: "satu", "dua" dan "tiga".
Jika seorang programmer menginginkan sebuah string dengan nilai beberapa variabel diinterpolasi:
shell harus benar-benar tidak menghapus tanda kutip: string yang berisi spasi akan diuraikan sebagai 3 string yang lebih kecil.
sumber