[英]BASH: Execute commands stored in array
I am trying to execute a shell script like below我正在尝试执行如下所示的 shell 脚本
cmds=('uptime' 'free -m' 'nproc')
for cmd in ${cmds[@]};
do
echo $($cmd)
done
Execution is breaking when it comes to free -m
execution because of space.由于空间的原因,执行在free -m
执行方面正在中断。
vagrant@vagrant-ubuntu-trusty-64:~$ bash for_my_script.sh
03:42:50 up 56 min, 1 user, load average: 0.00, 0.00, 0.00
total used free shared buff/cache available
Mem: 499928 108516 43204 1844 348208 366140
Swap: 0 0 0
for_my_script.sh: line 5: -m: command not found
1
vagrant@vagrant-ubuntu-trusty-64:~$
I tried iterating with for by storing commands in variable我尝试通过将命令存储在变量中来迭代 for
vagrant@vagrant-ubuntu-trusty-64:~$ cmds="uptime,free -m"
vagrant@vagrant-ubuntu-trusty-64:~$ for cmd in "${cmds//,/ }"; do echo "$($cmd)"; done
uptime: invalid option -- 'm'
vagrant@vagrant-ubuntu-trusty-64:~$ cmds="uptime,'free -m'"
vagrant@vagrant-ubuntu-trusty-64:~$ for cmd in "${cmds//,/ }"; do echo "$($cmd)"; done
uptime: invalid option -- 'm'
With no success.没有成功。
is touching IFS
is the only way for this type of problem?接触IFS
是解决此类问题的唯一方法吗? any inputs are much appreciated.任何输入都非常感谢。
Thank you.谢谢你。
The accepted answer still involves unquoted strings , which are discouraged and error-prone.接受的答案仍然涉及不带引号的字符串,这是不鼓励和容易出错的。 You could use eval
as @Fravadona suggests, but eval
is also hard to work with properly/safely .您可以按照@Fravadona 的建议使用eval
,但eval
也很难正确/安全地使用。
Instead, consider creating functions to wrap the commands you want to run;相反,请考虑创建函数来包装要运行的命令; then you don't need to deal with nested arguments within strings.那么你不需要处理字符串中的嵌套参数。 Functions also makes it easy to compose more complex behavior (pipelines, conditionals, etc.) without complicating the execution loop.函数还可以轻松组合更复杂的行为(管道、条件等),而不会使执行循环复杂化。 Something like:就像是:
do_free() { free -m; }
cmds=(uptime do_free nproc)
for cmd in "${cmds[@]}"; do
"$cmd" # notice that you don't need echo $("$cmd"); it's generally redundant
done
You could create wrappers for uptime
and nproc
too for consistency, but it's not necessary as long as you don't need to pass any arguments.您可以为uptime
和nproc
创建包装器以保持一致性,但只要您不需要传递任何参数,就没有必要。
For a more complete example of what I'm suggesting see this heartbeat script and the COMMANDS
array in particular.有关我建议的更完整示例,请参阅此心跳脚本和特别是COMMANDS
数组。
You have to change your code from:您必须从以下位置更改代码:
cmds=('uptime' 'free -m' 'nproc')
for cmd in ${cmds[@]};
do
echo $(${cmd})
done
into进入
cmds=('uptime' 'free -m' 'nproc')
for cmd in "${cmds[@]}";
do
echo $(${cmd})
done
You missed double quotes around ${cmds[@]}
.您错过了${cmds[@]}
周围的双引号。
In this specific case the right way IS to use eval
, so your script should be:在这种特定情况下,正确的方法是使用eval
,因此您的脚本应该是:
cmds=('uptime' 'free -m' 'nproc')
for cmd in "${cmds[@]}"
do
eval "$cmd"
done
note: That is, if you store each command the same way that you would type them in the terminal.注意:也就是说,如果您以与在终端中键入命令相同的方式存储每个命令。
Let's see a few examples:让我们看几个例子:
# cmd='echo "a b"'
# eval "$cmd"
a b
# $cmd
"a b"
# echo $(${cmd})
"a b"
#
# cmd='echo a; echo b'
# eval "$cmd"
a
b
# $cmd
a; echo b
# echo $(${cmd})
a; echo b
#
# cmd='echo;'
# eval "$cmd"
# $cmd
bash: echo;: command not found...
# echo $(${cmd})
bash: echo;: command not found...
#
AL: eval
is evil when you don't know how and when to use it AL:当你不知道如何以及何时使用它时, eval
是邪恶的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.