Как правильно вызвать команду, хранящуюся в переменной?
Есть ли разница между 1 и 2?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
shell
unix
parameter-expansion
Владимир Безуглый
источник
источник
Ответы:
Оболочки Unix перед их выполнением выполняют серию преобразований в каждой строке ввода. Для большинства оболочек это выглядит примерно так (взято из
bash
справочной страницы):Использование
$cmd
напрямую заменяет его вашей командой на этапе раскрытия параметров, а затем он претерпевает все последующие преобразования.Использование
eval "$cmd"
ничего не делает до фазы удаления цитаты, где$cmd
возвращается как есть и передается в качестве параметраeval
функции, чья функция заключается в повторном запуске всей цепочки перед выполнением.В общем, в большинстве случаев они одинаковы и различаются, когда ваша команда использует шаги преобразования вплоть до раскрытия параметров. Например, используя раскладку скобок:
$ cmd="echo foo{bar,baz}" $ $cmd foo{bar,baz} $ eval "$cmd" foobar foobaz
источник
eval "$cmd"
без письмаeval
?$($cmd)
?${$cmd}
?eval
операция анализирует данные как синтаксис; поэтому он очень чувствителен к безопасности, и делать это неявно было бы очень плохим тоном.Если вы просто сделаете это,
eval $cmd
когда мы это сделаемcmd="ls -l"
(в интерактивном режиме и в сценарии), мы получим желаемый результат. В вашем случае у вас есть канал с grep без шаблона, поэтому часть grep выйдет из строя с сообщением об ошибке. Просто$cmd
создаст сообщение «команда не найдена» (или что-то подобное). Поэтому попробуйте использовать eval и использовать готовую команду, а не ту, которая генерирует сообщение об ошибке.источник
$cmd
просто заменит переменную ее значением, которое будет выполнено в командной строке.eval "$cmd"
выполняет расширение переменных и подстановку команд перед выполнением результирующего значения в командной строкеВторой метод полезен, когда вы хотите запускать команды, которые не являются гибкими, например.
for i in {$a..$b}
Цикл форматирования не будет работать, потому что он не позволяет использовать переменные.
В этом случае обходной путь является использование канала для bash или eval.
Протестировано на Mac OSX 10.6.8, Bash 3.2.48
источник
Я думаю тебе стоит поставить
(обратная кавычка) вокруг вашей переменной.
источник