Как сохранить команду в переменной в Linux?
Я хотел бы сохранить команду для использования в более поздний период в переменной (не вывод команды, а сама команда)
у меня есть простой скрипт следующим образом:
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
любая идея, как я мог бы хранить такую команду (с трубами/несколькими командами) в переменной для последующего использования?
4 ответа:
сделать не использовать
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
не имеет массивов, поэтому самое близкое, что вы можете сделать, это создать список элементов в позиционных параметрах. Вот это POSIXsh
способ запуска программы mail# POSIX sh # Usage: sendto subject address [address ...] sendto() { subject= 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" "$@" }
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
то же самое с backtick
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 только строки, которыми вы управляете, никогда не строки, поступающие от ненадежного пользователя или построенные из ненадежного пользовательского ввода.