Este não é um problema trivial. O Shell executa a remoção de cotação antes de chamar a função, portanto, não há como a função recriar as cotações exatamente como você as digitou.
No entanto, se você quiser imprimir uma sequência que pode ser copiada e colada para repetir o comando, há duas abordagens diferentes que você pode seguir:
- Crie uma sequência de comandos a ser executada
eval
e passe essa sequência paradry_run
- Cite os caracteres especiais do comando
dry_run
antes de imprimir
Usando eval
Veja como você pode usar eval
para imprimir exatamente o que é executado:
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"
}
Resultado:
su - webuser1 -c "cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com"
Observe a quantidade louca de citações - você tem um comando dentro de um comando, que fica feio rapidamente. Cuidado: o código acima terá problemas se suas variáveis contiverem espaços em branco ou caracteres especiais (como aspas).
Citando caracteres especiais
Essa abordagem permite que você escreva código de forma mais natural, mas a saída é mais difícil para os humanos lerem devido à maneira rápida e suja de shell_quote
ser implementada:
# 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"
}
Resultado:
'su' '-' 'webuser1' '-c' 'cd /home/webuser1/public_html && git log -1 -p|mail -s '\''Git deployment on webuser1'\'' user@domain.com'
Você pode melhorar a legibilidade da saída alterando shell_quote
para caracteres especiais de escape com barra invertida em vez de agrupar tudo entre aspas simples, mas é difícil fazer isso corretamente.
Se você fizer a shell_quote
abordagem, poderá construir o comando para transmitir de su
uma maneira mais segura. O seguinte funcionaria mesmo se ${GIT_WORK_TREE}
, ${mail_subject}
ou ${admin_email}
contivesse caracteres especiais (aspas simples, espaços, asteriscos, ponto e vírgula, etc.):
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"
}
Resultado:
'su' '-' 'webuser1' '-c' ''\''cd'\'' '\''/home/webuser1/public_html'\'' && git log -1 -p | '\''mail'\'' '\''-s'\'' '\''Git deployment on webuser1'\'' '\''user@domain.com'\'''