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