如何在shell脚本中的变量中存储命令?

问题描述 投票:87回答:4

我想存储一个命令,以便稍后在变量中使用(不是命令的输出,而是命令本身)

我有一个简单的脚本如下:

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

知道如何在变量中存储这样的命令(使用管道/多个命令)供以后使用吗?

linux bash variables command
4个回答
125
投票

使用eval:

x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"

31
投票

不要使用eval!它具有引入任意代码执行的主要风险。

BashFAQ-50 - I'm trying to put a command in a variable, but the complex cases always fail.

把它放在一个数组中,并用双引号"${arr[@]}"展开所有单词,不要让IFS分割由于Word Splitting引起的单词。

cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')

并查看里面数组的内容。 declare -p允许您在单独的索引中使用每个命令参数查看内部数组的内容。如果一个这样的参数包含空格,那么在添加到数组时引用内部将阻止它因为Word-Splitting而被拆分。

declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'

并执行命令

"${cmdArgs[@]}"
23:15:18

(或)共同使用bash函数来运行命令,

cmd() {
   date '+%H:%M:%S'
}

并将该函数称为just

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语句等


21
投票
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提醒我引用命令!

-8
投票

即使您以后需要使用它,也无需将命令存储在变量中。按照正常情况执行它。如果存储在变量中,则需要某种eval语句或调用一些不必要的shell进程来“执行变量”。

© www.soinside.com 2019 - 2024. All rights reserved.