これはささいな問題ではありません。Shellは、関数を呼び出す前に引用の削除を実行するため、入力したとおりに関数が引用を再作成することはできません。
ただし、コピーして貼り付けてコマンドを繰り返すことができる文字列を出力できるようにするだけの場合は、次の2つの方法があります。
- 経由するコマンド文字列を作成し
eval
、その文字列を渡すdry_run
dry_run
印刷する前にコマンドの特殊文字を引用符で囲みます
使用する eval
eval
実行した内容を正確に印刷する方法は次のとおりです。
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"
}
出力:
su - webuser1 -c "cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com"
クレイジーな量の引用に注意してください-コマンド内のコマンド内にコマンドがあり、すぐに醜くなります。注意:変数に空白や特殊文字(引用符など)が含まれている場合、上記のコードには問題があります。
特殊文字の引用
このアプローチにより、より自然にコードを記述できますが、shell_quote
実装が迅速で汚いため、出力は人間にとって読みづらくなります。
# 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"
}
出力:
'su' '-' 'webuser1' '-c' 'cd /home/webuser1/public_html && git log -1 -p|mail -s '\''Git deployment on webuser1'\'' user@domain.com'
shell_quote
すべてを一重引用符で囲むのではなく、バックスラッシュエスケープ特殊文字に変更することで、出力を読みやすくすることができますが、正しく行うのは困難です。
shell_quote
アプローチを行う場合su
、より安全な方法で渡すコマンドを作成できます。以下は動作していてもなり${GIT_WORK_TREE}
、${mail_subject}
または${admin_email}
特殊文字(単一引用符、スペース、アスタリスク、セミコロンなど)を含んでいました:
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"
}
出力:
'su' '-' 'webuser1' '-c' ''\''cd'\'' '\''/home/webuser1/public_html'\'' && git log -1 -p | '\''mail'\'' '\''-s'\'' '\''Git deployment on webuser1'\'' '\''user@domain.com'\'''