Я хотел бы сохранить команду для использования в более позднем периоде в переменной (не вывод команды, а сама команда)
У меня есть простой script следующим образом:
command="ls";
echo "Command: $command"; #Output is: Command: ls
b=`$command`;
echo $b; #Output is: public_html REV test... (command worked successfully)
Однако, когда я пытаюсь сделать что-то более сложное, он терпит неудачу. Например, если я делаю
command="ls | grep -c '^'";
Вывод:
Command: ls | grep -c '^'
ls: cannot access |: No such file or directory
ls: cannot access grep: No such file or directory
ls: cannot access '^': No such file or directory
Любая идея, как я мог хранить такую команду (с помощью труб/нескольких команд) в переменной для последующего использования?
Ответ 1
Используйте eval:
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
Ответ 2
Не используйте eval
! Это имеет большой риск введения произвольного выполнения кода.
BashFAQ-50 - я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу.
Поместите его в массиве и развернуть все слова с двойными кавычками "${arr[@]}"
, чтобы не допустить IFS
разделить слова из - за расщепление Слова.
cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')
и посмотрите содержимое массива внутри. declare -p
позволяет вам видеть содержимое массива внутри с каждым параметром команды в отдельных индексах. Если один такой аргумент содержит пробелы, заключение в кавычки при добавлении в массив предотвратит его разбиение из-за разбиения по словам.
declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'
и выполнить команды как
"${cmdArgs[@]}"
23:15:18
(или) вообще использовать функцию bash
для запуска команды,
cmd() {
date '+%H:%M:%S'
}
и вызвать функцию как раз
cmd
POSIX sh
не имеет массивов, поэтому самое близкое, что вы можете получить, - это создать список элементов в позиционных параметрах. Здесь POSIX sh
способ запустить почтовую программу
# POSIX sh
# Usage: sendto subject address [address ...]
sendto() {
subject=$1
shift
first=1
for addr; do
if [ "$first" = 1 ]; then set --; first=0; fi
set -- "$@" --recipient="$addr"
done
if [ "$first" = 1 ]; then
echo "usage: sendto subject address [address ...]"
return 1
fi
MailTool --subject="$subject" "$@"
}
Обратите внимание, что этот подход может обрабатывать только простые команды без перенаправлений. Он не может обрабатывать перенаправления, конвейеры, циклы for/while, операторы if и т.д.
Ответ 3
var=$(echo "asdf")
echo $var
# => asdf
Используя этот метод, команда сразу оценивается и ее возвращаемое значение сохраняется.
stored_date=$(date)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
То же самое с клюшкой
stored_date='date'
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
Использование eval в $(...)
не сделает его вычисленным позже
stored_date=$(eval "date")
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
Используя eval, он оценивается при использовании eval
stored_date="date" # < storing the command itself
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:05 EST 2015
# (wait a few seconds)
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:16 EST 2015
# ^^ Time changed
В приведенном выше примере, если вам нужно запустить команду с аргументами, поместите их в строку, которую вы храните
stored_date="date -u"
# ...
Для скриптов bash это редко актуально, но последнее замечание. Будьте осторожны с eval
. Eval - это только строки, которыми вы управляете, но не строки, полученные от ненадежного пользователя или созданные из ненадежного пользовательского ввода.
- Спасибо @CharlesDuffy за напоминание процитировать команду!
Ответ 4
Для bash сохраните свою команду следующим образом:
command="ls | grep -c '^'"
Выполните свою команду следующим образом:
echo $command | bash
Ответ 5
Не нужно хранить команды в переменных, даже если вам нужно использовать их позже. просто выполните его как обычно. Если вы храните переменную, вам понадобится какой-то оператор eval
или вызвать ненужный процесс оболочки для "выполнения вашей переменной".