Saya telah melihat beberapa topik yang serupa, tetapi mereka merujuk pada tidak mengutip variabel, yang saya tahu dapat menyebabkan hasil yang tidak diinginkan.
Saya melihat kode ini dan bertanya-tanya apakah akan mungkin untuk menyuntikkan sesuatu untuk dijalankan ketika baris kode ini dijalankan:
echo run after_bundle
Jawaban:
Untuk kasus khusus
mengutip tidak diperlukan. Tidak ada kutipan yang diperlukan karena argumennya
echo
adalah string statis yang tidak mengandung ekspansi variabel atau penggantian perintah, dll. Mereka "hanya dua kata" (dan seperti yang ditunjukkan Stéphane , mereka juga dibuat dari set karakter portabel )."Bahaya" muncul ketika Anda berurusan dengan data variabel yang dapat diperluas atau ditafsirkan oleh shell. Dalam kasus seperti itu, harus diperhatikan bahwa shell melakukan hal yang benar dan hasilnya adalah apa yang dimaksudkan.
Dua pertanyaan berikut berisi informasi yang relevan tentang itu:
echo
kadang-kadang digunakan untuk "melindungi" perintah yang berpotensi berbahaya dalam jawaban di situs ini. Misalnya, saya dapat menunjukkan cara menghapus file atau memindahkan file ke tujuan baru menggunakanatau
Ini akan menampilkan perintah pada terminal alih-alih menghapus atau mengganti nama file. Pengguna kemudian dapat memeriksa perintah, memutuskan bahwa mereka terlihat baik-baik saja, hapus
echo
dan jalankan lagi.Perintah Anda
echo run after_bundle
dapat berupa instruksi kepada pengguna, atau mungkin kode "dikomentari" yang terlalu berbahaya untuk dijalankan tanpa mengetahui konsekuensinya.Dengan menggunakan
echo
seperti ini, kita harus tahu apa yang dilakukan perintah yang dimodifikasi dan kita harus menjamin bahwa perintah yang dimodifikasi itu benar - benar aman (kemungkinan tidak akan jika itu berisi pengalihan, dan menggunakannya pada pipa tidak berfungsi, dll.)sumber
echo rm "first file.txt" "second file.txt"
dengan cara apa pun berbedaecho rm "first" "file.txt" "second" "file.txt"
, output dari keduanya sama. Jika Anda ingin menghasilkan perintah shell sebagai output, seseorang harus menggunakanprintf '%q ' rm "first file.txt" "second file.txt"; echo
atau sesuatu yang setara yang menghasilkan kembali kutipan sintaksis yang mengevaluasi keargv
berlalu.sh
bukan pola yang tidak biasa, dan melihat orang bertanya "mengapafoo
bekerja ketika saya menjalankannya pada baris perintah, tetapi skrip ini yang memancarkan string yang tepat denganecho
di depan baris tidak? " terjadi sepanjang waktu di sini. Lebih penting lagi, hasil debugging tidak membantu jika menyembunyikan bug Anda - dan jika bug Anda terkait dengan mengutip, makaecho
tidak akan mengungkapkannya.Hanya catatan tambahan di atas jawaban baik @ Kusalananda .
baik-baik saja karena tidak ada karakter dalam 3 argumen¹ yang dilewatkan untuk
echo
mengandung karakter yang khusus untuk shell.Dan (poin tambahan yang ingin saya buat di sini) tidak ada sistem lokal di mana byte tersebut dapat diterjemahkan ke karakter yang khusus untuk shell.
Semua karakter itu dalam apa yang POSIX sebut sebagai set karakter portabel . Karakter-karakter tersebut harus ada dan dikodekan sama di semua set karakter pada sistem POSIX².
Sehingga baris perintah akan diinterpretasikan sama terlepas dari lokalnya.
Sekarang, jika kita mulai menggunakan karakter di luar set karakter portabel, itu adalah ide yang baik untuk mengutip mereka bahkan jika mereka tidak khusus untuk shell, karena di lokal lain, byte yang membentuknya dapat ditafsirkan sebagai karakter berbeda yang dapat menjadi khusus untuk shell. Perhatikan bahwa apakah Anda menggunakan
echo
atau perintah lain, masalahnya bukan padaecho
tetapi dengan bagaimana shell mengurai kodenya.Misalnya dalam UTF-8:
Itu
à
dikodekan sebagai 0xc3 0xa0. Sekarang, jika Anda memiliki baris kode dalam skrip shell dan skrip shell dipanggil oleh pengguna yang menggunakan lokal yang charsetnya bukan UTF-8, dua byte itu bisa membuat karakter yang sangat berbeda.Misalnya, dalam
fr_FR.ISO8859-15
lokal, lokal Prancis tipikal menggunakan charset byte tunggal standar yang mencakup bahasa Prancis (yang sama digunakan untuk sebagian besar bahasa Eropa barat termasuk bahasa Inggris), bahwa byte 0xc3 ditafsirkan sebagaiÃ
karakter dan 0xa0 sebagai non- melanggar karakter ruang.Dan pada beberapa sistem seperti NetBSD³, bahwa ruang tanpa putus dianggap sebagai karakter kosong (
isblank()
di atasnya mengembalikan true, itu cocok dengan[[:blank:]]
) dan kerang sepertibash
karenanya memperlakukannya sebagai pembatas token dalam sintaks mereka.Itu berarti bahwa alih-alih menjalankan
echo
dengan$'voil\xc3\xa0'
sebagai argumen, mereka menjalankannya dengan$'voil\xc3'
sebagai argumen, yang berarti tidak akan mencetakvoilà
dengan benar.Ia mendapat lebih buruk dengan set karakter Cina seperti BIG5, BIG5-HKSCS, GB18030, GBK yang memiliki banyak karakter yang encoding berisi encoding sama dengan
|
,`
,\
(untuk nama yang terburuk) (juga bahwa SJIS menggelikan, alias Microsoft Kanji, kecuali bahwa itu¥
bukan\
, tapi masih diperlakukan\
oleh sebagian besar alat karena dikodekan sebagai 0x5c di sana).Misalnya, jika di
zh_CN.gb18030
lokal Cina, Anda menulis skrip seperti:Skrip itu akan menampilkan
詜 reboot
dalam lokal menggunakan GB18030 atau GBK,唰 reboot
di lokal menggunakan BIG5 atau BIG5-HKSCS, tetapi di lokal C menggunakan ASCII atau lokal menggunakan ISO8859-15 atau UTF-8, akan menyebabkanreboot
dijalankan karena pengkodean GB18030 dari詜
adalah 0xd4 0x7c dan 0x7c adalah pengkodean|
dalam ASCII sehingga kami akhirnya menjalankan:(yang mewakili byte 0xd4 diberikan di lokal). Contoh menggunakan yang kurang berbahaya
uname
alih-alihreboot
:(
uname
Dijalankan).Jadi saran saya adalah mengutip semua string yang berisi karakter di luar set karakter portabel.
Namun perhatikan bahwa karena penyandian
\
dan`
ditemukan dalam penyandian beberapa karakter tersebut, lebih baik untuk tidak menggunakan\
atau"..."
atau$'...'
(di dalamnya mana`
dan / atau\
masih istimewa), tetapi'...'
alih - alih mengutip karakter di luar rangkaian karakter portabel.Saya tidak mengetahui adanya sistem yang memiliki lokal di mana charset memiliki karakter apa pun (selain
'
tentu saja itu sendiri) yang penyandiannya berisi penyandian'
, jadi itu'...'
pasti yang paling aman.Perhatikan bahwa beberapa shell juga mendukung
$'\uXXXX'
notasi untuk mengekspresikan karakter berdasarkan titik kode Unicode mereka. Dalam cangkang sukazsh
danbash
, karakter dimasukkan disandikan dalam charset lokal (meskipun dapat menyebabkan perilaku yang tidak terduga jika charset itu tidak memiliki karakter itu). Itu memungkinkan Anda menghindari memasukkan karakter non-ASCII dalam kode shell Anda.Di atas:
Atau:
(dengan peringatan itu bisa mematahkan skrip ketika dijalankan di lokal yang tidak memiliki karakter tersebut).
Atau lebih baik, karena
\
juga khusus untukecho
(atau setidaknya beberapaecho
implementasi, setidaknya yang sesuai Unix):(catatan yang
\
juga khusus dalam argumen pertamaprintf
, jadi karakter non-ASCII juga lebih baik dihindari di sana jika mereka mungkin mengandung pengkodean\
).Perhatikan bahwa Anda juga bisa melakukan:
(Itu akan berlebihan tetapi bisa memberi Anda ketenangan pikiran jika Anda tidak yakin karakter mana yang ada di set karakter portabel)
Juga pastikan untuk tidak pernah menggunakan
`...`
bentuk substitusi perintah kuno (yang memperkenalkan pemrosesan backslash tingkat lain), tetapi gunakan$(...)
sebagai gantinya.¹ teknis,
echo
juga diberikan sebagai argumen keecho
utilitas (untuk menceritakannya bagaimana itu dipanggil), ituargv[0]
danargc
adalah 3, meskipun dalam kebanyakan kerang saat iniecho
adalah builtin, sehinggaexec()
dari/bin/echo
file dengan daftar 3 argumen disimulasikan oleh kulit. Juga umum untuk mempertimbangkan daftar argumen sebagai mulai dengan yang kedua (argv[1]
untukargv[argc - 1]
) karena itulah yang sebagian besar ditindaklanjuti oleh perintah.² pengecualian untuk yang menjadi menggelikan
ja_JP.SJIS
lokal sistem FreeBSD yang charset tidak memiliki\
atau~
karakter!³ perhatikan bahwa walaupun banyak sistem (FreeBSD, Solaris, bukan yang GNU) menganggap U + 00A0 sebagai
[[:blank:]]
di dalam UTF-8 lokal, sedikit yang dilakukan di lokal lain seperti yang menggunakan ISO8859-15, mungkin untuk menghindari masalah seperti ini.sumber
echo
...", saya hanya menghitung 2 argumen yang diteruskan ke perintahecho
, argumen yang dapat saya hitung adalahrun
danafter_bundle
, ingin menjelaskan bagaimana Anda dihitung dan sampai 3 argumen?echo
). Lihat(exec -a foo /bin/echo --help)
pada sistem GNU dan dengan shell GNU untuk cara meneruskan argumen pertama yang sewenang-wenang ke/bin/echo
utilitas.$0
dan parameter posisi dalam shell.iconv
yangESC
dikonversi menjadi'
. Coba (sebagai contoh):printf '\x1b'|iconv -f utf8 -t IBM-937|xxd
'
. Cobaprintf '\u2804' | iconv -f utf8 -t BRF | xxd
. Ada pengkodean di mana ada banyak codepoint yang menjadi'
. Sekitar 8695 codepoint di UCS-4 menjadi'
. Cobaprintf '\U627' | iconv -cf utf-8 -t UCS-4
. Beberapa (37) pengkodean mengkonversi karakter 0x127 ke a'
. Cobaprintf '\U127' | iconv -cf utf8 -t UCS2 |xxd