Это не тривиальная проблема. Оболочка выполняет удаление кавычек перед вызовом функции, поэтому функция никак не может воссоздать кавычки в точности так, как вы их напечатали.
Однако, если вы просто хотите распечатать строку, которую можно скопировать и вставить, чтобы повторить команду, вы можете воспользоваться двумя различными способами:
- Создайте командную строку для запуска
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'\'''