Bash script - переменное содержимое как команда для запуска

159

У меня есть сценарий Perl, который дает мне определенный список случайных чисел, которые соответствуют строкам файла. Далее я хочу извлечь эти строки из файла, используя sed.

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var=$(perl test.pl test2 $count)

Переменная varвозвращает вывод , как: cat last_queries.txt | sed -n '12p;500p;700p'. Проблема в том, что я не могу запустить эту последнюю команду. Я пытался с $var, но вывод не является правильным (если я запускаю команду вручную, она работает нормально, так что никаких проблем нет). Как правильно это сделать?

PS: Конечно, я мог бы делать всю работу в Perl, но я пытаюсь научиться этому, потому что это может помочь мне в других ситуациях.

Barata
источник

Ответы:

215

Вам просто нужно сделать:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
$(perl test.pl test2 $count)

Однако, если вы хотите вызвать вашу команду Perl позже, и именно поэтому вы хотите присвоить ее переменной, то:

#!/bin/bash
count=$(cat last_queries.txt | wc -l)
var="perl test.pl test2 $count" # You need double quotes to get your $count value substituted.

...stuff...

eval $var

Согласно помощи Баша:

~$ help eval
eval: eval [arg ...]
    Execute arguments as a shell command.

    Combine ARGs into a single string, use the result as input to the shell,
    and execute the resulting commands.

    Exit Status:
    Returns exit status of command or success if command is null.
hmontoliu
источник
176

Вы, наверное, ищете eval $var.

Август Карлстрем
источник
3
Это сработало, когда $($cmd))не удалось. Это всегда говорит, что команда не найдена. Спасибо!
CMCDragonkai
2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

просто с вашим файлом вместо.

В этом примере я использовал файл / etc / password, используя специальную переменную ${RANDOM}(о которой я узнал здесь), и sedвыражение, которое у вас было, единственное отличие состоит в том, что я использую двойные кавычки вместо одинарных, чтобы разрешить расширение переменной.

nhed
источник
2

В случае, когда у вас есть несколько переменных, содержащих аргументы для команды, которую вы запускаете, а не просто одну строку, вы не должны использовать eval напрямую, так как это не получится в следующем случае:

function echo_arguments() {
  echo "Argument 1: $1"
  echo "Argument 2: $2"
  echo "Argument 3: $3"
  echo "Argument 4: $4"
}

# Note we are passing 3 arguments to `echo_arguments`, not 4
eval echo_arguments arg1 arg2 "Some arg"

Результат:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some
Argument 4: arg

Обратите внимание, что даже если «Some arg» был передан как один аргумент, evalсчитайте его как два.

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

# The regular bash eval works by jamming all its arguments into a string then
# evaluating the string. This function treats its arguments as individual
# arguments to be passed to the command being run.
function eval_command() {
  "$@";
}

Обратите внимание на разницу между выводом evalи новой eval_commandфункцией:

eval_command echo_arguments arg1 arg2 "Some arg"

Результат:

Argument 1: arg1
Argument 2: arg2
Argument 3: Some arg
Argument 4:
Ajedi32
источник
1
Для того, чтобы избежать оценки каждого элемента после того, как пространство, как и в первом примере с Eval, завернуть его в одинарные кавычки: eval 'echo_arguments arg1 arg2 "Some arg"'. Тогда результат будет таким же, как во втором примере.
Ноам Манос