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, але я намагаюся навчитися цьому, бо це могло б допомогти мені в інших ситуаціях.

Відповіді:


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.


2
line=$((${RANDOM} % $(wc -l < /etc/passwd)))
sed -n "${line}p" /etc/passwd

просто замість вашого файлу.

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


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

Зауважте, що, хоча "Деякі аргументи" були передані як один аргумент, 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:

1
Для того, щоб уникнути оцінки кожного елемента після того, як простір, як і в першому прикладі з Eval, загорнути його в одинарні лапки: eval 'echo_arguments arg1 arg2 "Some arg"'. Тоді вихід буде таким, як у вашому другому прикладі.
Ноам Манос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.