Я пытаюсь реализовать механизм пробного запуска для моего сценария и сталкиваюсь с проблемой удаления кавычек, когда команда передается в качестве аргумента функции и приводит к неожиданному поведению.
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"
}
Выход:
su - webuser1 -c cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com
Ожидаемое:
su - webuser1 -c "cd /home/webuser1/public_html && git log -1 -p|mail -s 'Git deployment on webuser1' user@domain.com"
С включенным printf вместо echo:
su - webuser1 -c cd\ /home/webuser1/public_html\ \&\&\ git\ log\ -1\ -p\|mail\ -s\ \'Git\ deployment\ on\ webuser1\'\ user@domain.com
Результат:
su: invalid option -- 1
Это не должно иметь место, если кавычки остались там, где они были вставлены. Я также пытался использовать "Eval", не так много различий. Если я удаляю вызов dry_run в email_admin, а затем запускаю скрипт, он прекрасно работает.
Ответы:
Попробуйте использовать
\"
вместо просто"
.источник
"$@"
должно сработать. На самом деле это работает для меня в этом простом тестовом примере:Вывод:
Отредактировано, чтобы добавить: вывод
echo $@
правильный. Это"
метасимвол, а не часть параметра. Вы можете доказать, что он работает правильно, добавивecho $5
вdry_run()
. Будет выводить все после-c
источник
Это не тривиальная проблема. Оболочка выполняет удаление кавычек перед вызовом функции, поэтому функция никак не может воссоздать кавычки в точности так, как вы их напечатали.
Однако, если вы просто хотите распечатать строку, которую можно скопировать и вставить, чтобы повторить команду, вы можете воспользоваться двумя различными способами:
eval
и передайте эту строкуdry_run
dry_run
Перед печатью укажите специальные символы командыС помощью
eval
Вот как вы можете использовать
eval
для печати именно то, что выполняется:Вывод:
Обратите внимание на сумасшедшее количество цитат - у вас есть команда внутри команды, которая быстро становится ужасной. Осторожно: приведенный выше код будет иметь проблемы, если ваши переменные содержат пробелы или специальные символы (например, кавычки).
Цитирование специальных символов
Этот подход позволяет вам писать код более естественно, но людям труднее его читать, потому что
shell_quote
реализован быстрый и грязный способ :Вывод:
Вы можете улучшить читабельность вывода, изменив
shell_quote
специальные символы на обратную косую черту вместо того, чтобы заключать все в одинарные кавычки, но это трудно сделать правильно.Если вы используете
shell_quote
подход, вы можетеsu
создать команду для более безопасной передачи . Следующее будет работать, даже если${GIT_WORK_TREE}
,${mail_subject}
или${admin_email}
содержит специальные символы (одинарные кавычки, пробелы, звездочки, точки с запятой и т. Д.):Вывод:
источник
Это сложно, вы можете попробовать другой подход, который я видел:
таким образом, вы просто устанавливаете DRY_RUN либо пустым, либо "echo" в верхней части вашего скрипта, и он либо делает это, либо просто повторяет его.
источник
Хороший вызов :) Это должно быть "легко", если у вас достаточно недавнего bash для поддержки
$LINENO
и$BASH_SOURCE
Вот моя первая попытка, надеясь, что она подойдет вам:
источник