Выполнить команду, которая является результатом выполнения сценария, имя которого находится в переменной

При проводке этот вопрос изначально, я полностью misworded его, получая другой, разумный, но другой вопрос, который правильно ответил здесь.

Ниже приводится правильная версия вопроса, который я изначально хотел задать.

В одном из моих сценариев Bash есть точка, в которой у меня есть переменная SCRIPT который содержит /path/to/an/exe который при выполнении выводит line to be executed.

Что в конечном итоге нужно сделать моему сценарию, так это выполнить это line to be executed. Следовательно, последняя строка сценария

$($SCRIPT)

так что $SCRIPT расширяется до /path/to/an/exe, а также $(/path/to/an/exe) выполняет исполняемый файл и возвращает line to be executed, который затем выполняется.

Однако бег shellcheck на скрипте возникает эта ошибка:

In setscreens.sh line 7:
$($SCRIPT)
^--------^ SC2091: Remove surrounding $() to avoid executing output.

For more information:
  https://www.shellcheck.net/wiki/SC2091 -- Remove surrounding $() to avoid e...

Есть ли способ переписать это $($SCRIPT) более подходящим способом? eval здесь не очень помогает.

4 ответа

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

eval "$("$SCRIPT")"

$($SCRIPT)будет работать только в том случае, если команда может быть полностью вычислена, не используя ничего, кроме разделения слов и расширения имени пути, что обычно является редкой ситуацией. Если вместо этого программа выводит, например,grep "Hello World" или cmd > file.txt тогда тебе понадобится eval или эквивалент.

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

set -- "$SCRIPT"

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

"$@"

Это работает, если ваш вывод из SCRIPTсодержит несколько слов, например настраиваемые флаги, которые необходимо запустить. Поскольку это выполняется в вашей текущей интерактивной оболочке, убедитесь, что запускаемая команда не уязвима для внедрения кода. Вы можете сделать один шаг осторожности и запустить свою команду в суб-оболочке, чтобы не допустить воздействия на вашу родительскую среду, выполняя( "$@" ; )

Или используйте shellcheck disable=SCnnnn чтобы отключить предупреждение и воспользоваться случаем, чтобы прокомментировать явное намерение, вместо того, чтобы уклоняться от обнаружения, скрываясь за промежуточной переменной или массивом аргументов.

#!/usr/bin/env bash

# shellcheck disable=SC2091 # Intentional execution of the output
"$("$SCRIPT")"

Отключение shellcheck с помощью комментария проясняет намерение и сообщает, что сомнительный код не является ошибкой, а является осознанным выбором дизайна реализации.

Вы можете сделать это за 2 шага

command_from_SCRIPT=$($SCRIPT)
$command_from_SCRIPT

и он чистый в Shellcheck

Другие вопросы по тегам