如何将命令存储在Linux中的变量中?

时间:2021-04-15 00:37:54

I would like to store a command to use at a later period in a variable (not the output of the command, but the command itself)

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

I have a simple script as follows:

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

command="ls";
echo "Command: $command"; #Output is: Command: ls

b=`$command`;
echo $b; #Output is: public_html REV test... (command worked successfully)

However, when I try something a bit more complicated, it fails. For example, if I make

然而,当我尝试更复杂的事情时,它失败了。例如,如果我

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

The output is:

的输出是:

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

Any idea how I could store such a command (with pipes/multiple commands) in a variable for later use?

您知道我如何将这样一个命令(带有管道/多个命令)存储在一个变量中以便以后使用吗?

4 个解决方案

#1


92  

Use eval.

使用eval。

x="ls | wc"
eval $x
y=`eval $x`
echo $y

#2


19  

var=$(echo "asdf")
echo $var
# => asdf

Using this method, the command is immediately evaluated and it's return value is stored.

使用此方法,将立即对命令进行评估,并存储其返回值。

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

Same with 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

Using eval in the $(...) will not make it evaluated later

在$(…)中使用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

Using eval, it is evaluated when eval is used

使用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

In the above example, if you need to run a command with arguments, put them in the string you are storing

在上面的示例中,如果您需要运行带有参数的命令,请将它们放在正在存储的字符串中

stored_date="date -u"
# ...

For bash scripts this is rarely relevant, but one last note. Be careful with eval. Eval only strings you control, never strings coming from an untrusted user or built from untrusted user input.

对于bash脚本,这很少是相关的,但是最后要注意一点。小心使用eval。Eval只有您控制的字符串,从不来自不可信用户的字符串,或者由不可信的用户输入构建。

#3


16  

Do not use eval! It has a major risk of introducing arbitrary code execution.

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

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

Put it in an array and expand all the words with double-quotes "${arr[@]}" to not let the IFS split the words due to Word Splitting.

将它放在一个数组中,并展开带有双引号的“${arr[@]}”的所有单词,以避免IFS由于单词分裂而导致单词分裂。

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

and see the contents of the array inside. The declare -p allows you see the contents of the array inside with each command parameter in separate indices. If one such argument contains spaces, quoting inside while adding to the array will prevent it from getting split due to Word-Splitting.

并查看数组的内容。声明-p允许您查看数组的内容,每个命令参数都包含在单独的索引中。如果一个这样的参数包含空格,那么在数组中添加引用将防止它由于单词分裂而被分割。

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

and execute the commands as

并执行命令。

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

(or) altogether use a bash function to run the command,

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

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

and call the function as just

调用这个函数

cmd

POSIX sh has no arrays, so the closest you can come is to build up a list of elements in the positional parameters. Here's a POSIX sh way to run a mail program

POSIX sh没有数组,因此您可以访问的最接近的是在位置参数中构建元素列表。这里有一个运行邮件程序的POSIX方式

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

#4


-7  

Its is not necessary to store commands in variables even as you need to use it later. just execute it as per normal. If you store in variable, you would need some kind of eval statement or invoke some unnecessary shell process to "execute your variable".

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

#1


92  

Use eval.

使用eval。

x="ls | wc"
eval $x
y=`eval $x`
echo $y

#2


19  

var=$(echo "asdf")
echo $var
# => asdf

Using this method, the command is immediately evaluated and it's return value is stored.

使用此方法,将立即对命令进行评估,并存储其返回值。

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

Same with 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

Using eval in the $(...) will not make it evaluated later

在$(…)中使用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

Using eval, it is evaluated when eval is used

使用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

In the above example, if you need to run a command with arguments, put them in the string you are storing

在上面的示例中,如果您需要运行带有参数的命令,请将它们放在正在存储的字符串中

stored_date="date -u"
# ...

For bash scripts this is rarely relevant, but one last note. Be careful with eval. Eval only strings you control, never strings coming from an untrusted user or built from untrusted user input.

对于bash脚本,这很少是相关的,但是最后要注意一点。小心使用eval。Eval只有您控制的字符串,从不来自不可信用户的字符串,或者由不可信的用户输入构建。

#3


16  

Do not use eval! It has a major risk of introducing arbitrary code execution.

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

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

Put it in an array and expand all the words with double-quotes "${arr[@]}" to not let the IFS split the words due to Word Splitting.

将它放在一个数组中,并展开带有双引号的“${arr[@]}”的所有单词,以避免IFS由于单词分裂而导致单词分裂。

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

and see the contents of the array inside. The declare -p allows you see the contents of the array inside with each command parameter in separate indices. If one such argument contains spaces, quoting inside while adding to the array will prevent it from getting split due to Word-Splitting.

并查看数组的内容。声明-p允许您查看数组的内容,每个命令参数都包含在单独的索引中。如果一个这样的参数包含空格,那么在数组中添加引用将防止它由于单词分裂而被分割。

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

and execute the commands as

并执行命令。

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

(or) altogether use a bash function to run the command,

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

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

and call the function as just

调用这个函数

cmd

POSIX sh has no arrays, so the closest you can come is to build up a list of elements in the positional parameters. Here's a POSIX sh way to run a mail program

POSIX sh没有数组,因此您可以访问的最接近的是在位置参数中构建元素列表。这里有一个运行邮件程序的POSIX方式

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

#4


-7  

Its is not necessary to store commands in variables even as you need to use it later. just execute it as per normal. If you store in variable, you would need some kind of eval statement or invoke some unnecessary shell process to "execute your variable".

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