Как отправить переменную во встроенный shell-скрипт?

26

Я запускаю следующий скрипт:

VAR="Test"
sh -c 'echo "Hello $VAR"'

Но я получаю:

# ./test.sh
Hello

Как я могу отправить переменную VARмоего скрипта в оболочку, созданную с помощью sh -c '...'?

Матье Наполи
источник

Ответы:

44

Либо используйте, exportчтобы превратить его в переменную окружения, либо передайте его непосредственно в команду.

VAR="Test" sh -c 'echo "Hello $VAR"'

VAR="Test"
export VAR
sh -c 'echo "Hello $VAR"'

Избегайте использования двойных кавычек вокруг кода оболочки, чтобы разрешить интерполяцию, поскольку это приводит к уязвимостям внедрения команд, как в:

sh -c "echo 'Hello $ VAR'"

вызывая перезагрузку, если вызывается, когда $VARсодержит что-то вроде';reboot #

Игнасио Васкес-Абрамс
источник
Не очень практично (у меня есть несколько переменных, и я не хочу, чтобы они были переменными среды), но это работает, спасибо!
Матье Наполи
3
@Matthieu: Они устанавливаются только как переменные окружения для детей вашего процесса , если вас это беспокоит.
Писквор
5
Просто к вашему сведению, вы также можете сделать export var="Test"в одну строку.
user606723
@Piskvor хорошо спасибо за точность, это прекрасно тогда.
Матье Наполи
9

Вот еще один способ передачи переменных sh -c(в качестве позиционных аргументов):

{
VAR="world"
VAR2='!'
sh -c 'echo "Hello ${0}${1}"' "$VAR" "$VAR2"
}
Бен
источник
1
(+1) Чтобы держать его в большей степени в соответствии с обычным ожиданием $ 1 $ 2 для переменных скрипта, он может иметь фиктивное значение для $ 0. Это позволит $@работать как положено, например. sh -c 'echo "Hello $@"' _ "$VAR" "$VAR2"`
Питер.O
2
@ Peter.O Вместо того, чтобы использовать «_», я бы использовал «sh» или разумное имя, чтобы дать этой команде, так как это $0отображается в сообщениях об ошибках / предупреждениях оболочкой.
Стефан Шазелас
5

Если вы не хотите экспортировать их как переменные среды, вот прием, который вы могли бы сделать. Сохраните определение variabe в файл .var_init.shи поместите его в свою под-оболочку следующим образом:

.var_init.sh

VAR="Test"

из командной строки:

sh -c ". .var_init.sh && echo \$VAR" # Make sure to properly escape the '$'

Таким образом, вы устанавливаете свои переменные только при выполнении вашей подоболочки.

rahmu
источник
... илиENV=.var_ini.sh sh -c '...'
Кусалананда
Обратите внимание, что если .var_init.shожидается, что это будет искать в текущем каталоге (в отличие от $PATH), это должно быть написано. ./var_init.sh
Стефан Шазелас