Linux 如何将命令存储在 shell 脚本的变量中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5615717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to store a command in a variable in a shell script?
提问by Benjamin
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?
知道如何将这样的命令(带有管道/多个命令)存储在变量中供以后使用吗?
采纳答案by Erik
Use eval:
使用评估:
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
回答by kurumi
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 进程来“执行您的变量”。
回答by Nate
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
在 the 中使用 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
. 仅评估您控制的字符串,而不是来自不受信任的用户或根据不受信任的用户输入构建的字符串。
- Thanks to @CharlesDuffy for reminding me to quote the command!
- 感谢@CharlesDuffy 提醒我引用命令!
回答by Inian
Do notuse 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.
BashFAQ-50- 我试图将命令放入变量中,但复杂的情况总是失败。
Put it in an array and expand all the words with double-quotes "${arr[@]}"
to notlet 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.
并查看里面数组的内容。的declare -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
POSIXsh
没有数组,所以最接近的是在位置参数中建立一个元素列表。这是sh
运行邮件程序的 POSIX方式
# 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" "$@"
}
Note that this approach can only handle simple commands with no redirections. It can't handle redirections, pipelines, for/while loops, if statements, etc
请注意,这种方法只能处理没有重定向的简单命令。它无法处理重定向、管道、for/while 循环、if 语句等
Another common use case is when running curl
with multiple header fields and payload. You can always define args like below and invoke curl
on the expanded array content
另一个常见用例是curl
使用多个标头字段和有效负载运行时。您始终可以像下面这样定义 args 并调用curl
扩展的数组内容
curlArgs=('-H' "keyheader: value" '-H' "2ndkeyheader: 2ndvalue")
curl "${curlArgs[@]}"
Another example,
另一个例子,
payload='{}'
hostURL='http://google.com'
authToken='someToken'
authHeader='Authorization:Bearer "'"$authToken"'"'
now that variables are defined, use an array to store your command args
现在定义了变量,使用数组来存储您的命令参数
curlCMD=(-X POST "$hostURL" --data "$payload" -H "Content-Type:application/json" -H "$authHeader")
and now do a proper quoted expansion
现在做一个适当的引用扩展
curl "${curlCMD[@]}"
回答by Derek Hazell
For bash, store your command like this:
对于 bash,像这样存储你的命令:
command="ls | grep -c '^'"
Run your command like this:
像这样运行你的命令:
echo $command | bash
回答by mpen
I tried various different methods:
我尝试了各种不同的方法:
printexec() {
printf -- "3[1;37m$3[0m"
printf -- " %q" "$@"
printf -- "\n"
eval -- "$@"
eval -- "$*"
"$@"
"$*"
}
Output:
输出:
$ 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
As you can see, only the third one, "$@"
gave the correct result.
如您所见,只有第三个"$@"
给出了正确的结果。
回答by Azerty
Be Careful registering an order with the: X=$(Command)
小心注册订单: X=$(Command)
This one is still executed Even before being called. To check and confirm this, you cand do:
即使在被调用之前,这个仍然被执行。要检查并确认这一点,您可以执行以下操作:
echo test;
X=$(for ((c=0; c<=5; c++)); do
sleep 2;
done);
echo note the 5 seconds elapsed