Подтвердить что ты не робот

Как выполнить команду, хранящуюся в переменной?

Каков правильный способ вызова некоторой команды, хранящейся в переменной?
Есть ли различия между 1 и 2?

#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
4b9b3361

Ответ 1

Unix-оболочки выполняют серию преобразований на каждой строке ввода перед их выполнением. Для большинства оболочек это выглядит примерно так (взято из bash manpage):

  • разбиение начального слова
  • расширение брекета
  • расширение тильды
  • параметр, переменная и арифметическое расширение
  • подстановка команд
  • вторичное расщепление слов
  • расширение пути (ака-глобус)
  • удаление цитаты

Использование $cmd напрямую заменяет его на вашу команду во время фазы расширения параметра, а затем претерпевает все следующие преобразования.

Использование eval "$cmd" ничего не делает до фазы удаления цитаты, где $cmd возвращается как есть, и передается как параметр в eval, функция которого состоит в том, чтобы снова запустить целую цепочку перед выполнением.

В основном, они в большинстве случаев одинаковы и отличаются, когда ваша команда использует шаги преобразования до расширения параметров. Например, используя расширение скобки:

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz

Ответ 2

Если вы просто сделаете eval $cmd когда мы делаем cmd="ls -l" (в интерактивном режиме и в script), получаем желаемый результат. В вашем случае у вас есть труба с grep без шаблона, поэтому команда grep завершится с сообщением об ошибке. Просто $cmd будет генерировать сообщение "команда не найдена" (или некоторое такое). Поэтому попробуйте использовать eval и используйте готовые команды, а не те, которые генерируют сообщение об ошибке.

Ответ 3

$cmd просто заменит переменную на значение, которое будет выполнено в командной строке. eval "$cmd" выполняет расширение переменной и подстановку команд перед выполнением результирующего значения в командной строке

2-й метод полезен, когда вы хотите выполнить команды, которые не являются гибкими, например.
for я in {$a..$b}
Цикл форматирования не будет работать, потому что он не допускает переменных.
В этом случае обходной путь - bash или eval.

Протестировано на Mac OSX 10.6.8, Bash 3.2.48

Ответ 4

Я думаю, вы должны поставить

'

(backtick) символы вокруг вашей переменной.