Saya mencoba untuk menerapkan jenis mekanisme run kering untuk skrip saya dan menghadapi masalah kutipan yang dilucuti ketika perintah dilewatkan sebagai argumen ke fungsi dan mengakibatkan perilaku yang tidak terduga.
dry_run () {
echo "$@"
#printf '%q ' "$@"
if [ "$DRY_RUN" ]; then
return 0
fi
"$@"
}
email_admin() {
echo " Emailing admin"
dry_run su - $target_username -c "cd $GIT_WORK_TREE && git log -1 -p|mail -s '$mail_subject' $admin_email"
echo " Emailed"
}
Output adalah:
su - webuser1 -c cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com
Diharapkan:
su - webuser1 -c "cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' [email protected]"
Dengan printf diaktifkan alih-alih gema:
su - webuser1 -c cd\ /home/webuser1/public_html\ \&\&\ git\ log\ -1\ -p\|mail\ -s\ \'Git\ deployment\ on\ webuser1\'\ user@domain.com
Hasil:
su: invalid option -- 1
Seharusnya tidak demikian jika kutipan tetap di tempat mereka dimasukkan. Saya juga sudah mencoba menggunakan "eval", tidak banyak perbedaan. Jika saya menghapus panggilan dry_run di email_admin dan kemudian menjalankan skrip, itu berfungsi dengan baik.
Jawaban:
Coba gunakan
\"
bukan hanya"
.sumber
"$@"
harus bekerja. Sebenarnya ini bekerja untuk saya dalam test case sederhana ini:Keluaran:
Diedit untuk menambahkan: output
echo $@
sudah benar. Ini"
adalah meta-karakter dan bukan bagian dari parameter. Anda dapat membuktikan bahwa itu benar bekerja dengan menambahkanecho $5
kedry_run()
. Ini akan menampilkan semuanya setelah-c
sumber
Ini bukan masalah sepele. Shell melakukan penghapusan kutipan sebelum memanggil fungsi, jadi tidak mungkin fungsi tersebut dapat membuat ulang kutipan persis seperti yang Anda ketik.
Namun, jika Anda hanya ingin dapat mencetak string yang dapat disalin dan ditempelkan untuk mengulangi perintah, ada dua pendekatan yang dapat Anda ambil:
eval
dan meneruskan string itu kedry_run
dry_run
sebelum dicetakMenggunakan
eval
Inilah cara yang dapat Anda gunakan
eval
untuk mencetak apa yang dijalankan:Keluaran:
Catat jumlah kutipan yang gila - Anda mendapat perintah di dalam perintah di dalam perintah, yang menjadi jelek dengan cepat. Hati-hati: Kode di atas akan bermasalah jika variabel Anda berisi spasi putih atau karakter khusus (seperti tanda kutip).
Mengutip Karakter Khusus
Pendekatan ini memungkinkan Anda untuk menulis kode lebih alami, tetapi hasilnya lebih sulit bagi manusia untuk dibaca karena cara cepat dan kotor
shell_quote
diterapkan:Keluaran:
Anda dapat meningkatkan keterbacaan output dengan mengubah
shell_quote
ke karakter khusus backslash-escape alih-alih membungkus segala sesuatu dalam tanda kutip tunggal, tetapi sulit dilakukan dengan benar.Jika Anda melakukan
shell_quote
pendekatan, Anda dapat membuat perintah untuk meneruskan dengansu
cara yang lebih aman. Berikut ini akan berfungsi bahkan jika${GIT_WORK_TREE}
,,${mail_subject}
atau${admin_email}
berisi karakter khusus (tanda kutip tunggal, spasi, tanda bintang, titik koma, dll.):Keluaran:
sumber
Itu sulit, Anda dapat mencoba pendekatan lain yang saya lihat:
dengan cara itu Anda hanya mengatur DRY_RUN menjadi kosong atau "bergema" di bagian atas skrip Anda dan apakah itu atau hanya gema itu.
sumber
Tantangan yang bagus :) Seharusnya "mudah" jika Anda memiliki bash yang cukup baru untuk mendukung
$LINENO
dan$BASH_SOURCE
Ini adalah upaya pertama saya, berharap ini sesuai dengan kebutuhan Anda:
sumber