В bash вы можете рассматривать строку как команду (и запускать ее) двумя разными способами:
#!/bin/bash
cmd = "echo -n sometext"
eval $cmd # Not sure if quotes make a difference here
а также
#!/bin/bash
cmd = "echo -n sometext"
$cmd # Not sure if quotes make a difference here either
Есть ли между ними разница? Есть ли ситуация, когда цитаты вокруг cmd имеют значение? А как насчет производительности?
cmd () { echo -n sometext; }Да, я знаю, внедрение кода и прочее. Хотя иногда это имеет место. Также не такая большая проблема со сценариями оболочки и веб-приложениями.





Да, есть разница :)
Вам нужно сначала понять, как работает eval. По сути, eval - это встроенная команда оболочки. Любой аргумент, переданный в eval, сначала обрабатывается как строка.
Возьмем пример ниже:
cmd = "echo -n sometext"
eval $cmd
Полный процесс выполнения этой команды выглядит следующим образом:
eval $cmd
+ eval echo -n sometext
++ echo -n sometext
sometext
Здесь сначала оценивается $ cmd, а затем вся строка передается команде eval в качестве аргумента. Затем eval оценивает команду, рассматривая первый аргумент как «команду или исполняемый файл», а затем запускается как обычная команда. Итак, здесь выполняется 2 раунда оценки для выполнения полной команды.
(ПРИМЕЧАНИЕ: символ + выше показывает пошаговое выполнение при использовании в режиме bash -x)
Основное следствие заключается в расширении переменных. С eval у нас есть два раунда расширения. Один, конечно, когда определен cmd, и второй, когда выполняется eval.
var = "inital"
cmd = "echo -n $var \$var"
var = "chanded in the mean time"
eval $cmd
inital chanded in the mean time
Однако, когда вы используете $cmd только без eval, bash позаботится обо всем, от расширения переменной до окончательного выполнения. Просто просмотрите детали окна отладки при работе только с $cmd.
$cmd
+ echo -n sometext
sometext
С точки зрения производительности, прямого использования $cmd вполне достаточно. Однако, когда вы пытаетесь использовать какую-либо внешнюю команду или сценарий, требующий изменения среды, вы можете использовать eval.
В cmd = "echo -n sometext" кавычки необходимы, иначе после "echo" bash вызовет ошибку, как показано ниже:
cmd=echo -n sometext
-n: command not found
Надеюсь, объяснение будет полезным.
Я понял, спасибо. Если вы не возражаете, я исправлю ваш ответ, добавив несколько баллов. Цитата заключалась в том, чтобы спросить, имеет ли значение eval "$cmd" и eval $cmd, и то же самое для $cmd без eval.
Конечно! Пожалуйста, обновите ответ. Кроме того, если вы сочтете это полезным, примите ответ;)
Ни то, ни другое не рекомендуется. Используйте функцию, а не переменную, для хранения кода, который будет выполняться.