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

时间:2011-04-11 00:33:14

标签: linux bash variables command

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

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

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

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

9 个答案:

答案 0 :(得分:117)

使用eval:

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

答案 1 :(得分:30)

使用eval!它存在引入任意代码执行的主要风险。

BashFAQ-50 - 我试图将命令放在变量中,但复杂的情况总是失败。

将其放入数组并使用双引号"${arr[@]}"将所有单词展开到而不是IFS分割由Word Splitting引起的单词。< / p>

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'
}

并将该函数调用为

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" "$@"
}

答案 2 :(得分:22)

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您控制的字符串,从不来自不受信任的用户的字符串或来自不受信任的用户输入的字符串。

答案 3 :(得分:0)

对于bash,请像这样存储您的命令:

command="ls | grep -c '^'"

像这样运行您的命令:

echo $command | bash

答案 4 :(得分:0)

我尝试了各种不同的方法:

printexec() {
  printf -- "\033[1;37m$\033[0m"
  printf -- " %q" "$@"
  printf -- "\n"
  eval -- "$@"
  eval -- "$*"
  "$@"
  "$*"
}

输出:

$ printexec echo  -e "foo\n" bar
$ echo -e foo\\n bar
foon bar
foon bar
foo
 bar
bash: echo -e foo\n bar: command not found

如您所见,只有第三个"$@"给出了正确的结果。

答案 5 :(得分:0)

请谨慎注册以下订单:X=$(Command)

这个仍然执行 甚至在被召唤之前。 要检查并确认这一点,您可以执行以下操作:

echo test;
X=$(for ((c=0; c<=5; c++)); do
sleep 2;
done);
echo note the 5 seconds elapsed

答案 6 :(得分:-1)

#!/bin/bash
#Note: this script works only when u use Bash. So, don't remove the first line.

TUNECOUNT=$(ifconfig |grep -c -o tune0) #Some command with "Grep".
echo $TUNECOUNT                         #This will return 0 
                                    #if you don't have tune0 interface.
                                    #Or count of installed tune0 interfaces.

答案 7 :(得分:-1)

首先有这方面的功能。但是如果你更喜欢 vars 那么你的任务可以这样完成:

Time.deltaTime

或者通过 tmp 文件

jumpForce

答案 8 :(得分:-8)

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