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:
- Bangun string perintah untuk dijalankan melalui
evaldan meneruskan string itu kedry_run
- Kutip karakter khusus perintah
dry_runsebelum dicetak
Menggunakan eval
Inilah cara yang dapat Anda gunakan evaluntuk mencetak apa yang dijalankan:
dry_run() {
printf '%s\n' "$1"
[ -z "${DRY_RUN}" ] || return 0
eval "$1"
}
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"
}
Keluaran:
su - webuser1 -c "cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com"
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_quotediterapkan:
# This function prints each argument wrapped in single quotes
# (separated by spaces). Any single quotes embedded in the
# arguments are escaped.
#
shell_quote() {
# run in a subshell to protect the caller's environment
(
sep=''
for arg in "$@"; do
sqesc=$(printf '%s\n' "${arg}" | sed -e "s/'/'\\\\''/g")
printf '%s' "${sep}'${sqesc}'"
sep=' '
done
)
}
dry_run() {
printf '%s\n' "$(shell_quote "$@")"
[ -z "${DRY_RUN}" ] || return 0
"$@"
}
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"
}
Keluaran:
'su' '-' 'webuser1' '-c' 'cd /home/webuser1/public_html && git log -1 -p|mail -s '\''Git deployment on webuser1'\'' user@domain.com'
Anda dapat meningkatkan keterbacaan output dengan mengubah shell_quoteke karakter khusus backslash-escape alih-alih membungkus segala sesuatu dalam tanda kutip tunggal, tetapi sulit dilakukan dengan benar.
Jika Anda melakukan shell_quotependekatan, Anda dapat membuat perintah untuk meneruskan dengan sucara 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.):
email_admin() {
echo " Emailing admin"
cmd=$(
shell_quote cd "${GIT_WORK_TREE}"
printf '%s' ' && git log -1 -p | '
shell_quote mail -s "${mail_subject}" "${admin_email}"
)
dry_run su - "${target_username}" -c "${cmd}"
echo " Emailed"
}
Keluaran:
'su' '-' 'webuser1' '-c' ''\''cd'\'' '\''/home/webuser1/public_html'\'' && git log -1 -p | '\''mail'\'' '\''-s'\'' '\''Git deployment on webuser1'\'' '\''user@domain.com'\'''