bash 从bash中的变量在for循环中执行命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19857658/
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
Execute command inside for loop from variable in bash
提问by tom
Trying to run commands defined in variables inside a for loop:
尝试运行在 for 循环内的变量中定义的命令:
somevar="Bit of text"
cmd1="command \"search '$somevar' here\""
cmd2="command \"search '$somevar' there\""
for cmd in cmd1 cmd2 ; do
eval $$cmd
ssh server1 eval $$cmd
done
I've put in the variations I have to consider such as the ssh inside the loop etc as these are needed in my script. I think the eval is the right direction, but the way that the quotes inside the command get interpreted comes through wrong.
我已经加入了我必须考虑的变化,例如循环内的 ssh 等,因为我的脚本需要这些。我认为 eval 是正确的方向,但是解释命令中的引号的方式是错误的。
回答by tom
Consider this broken example:
考虑这个破碎的例子:
$ cmd1="touch \"file with spaces\""
$ $cmd1
Quoting is handled before $cmd1
is expanded, so instead of one file this will create three files called "file
, with
, and spaces"
. One can use eval $cmd
to force quote removal after the expansion.
引用在$cmd1
展开之前处理,因此这将创建三个文件"file
,而不是一个文件,名为with
、 和spaces"
。可以使用eval $cmd
在扩展后强制删除引用。
Even though it uses eval
, the line eval \$$cmd
has that same quoting problem since \$$cmd
expands to $cmd1
, which is then evaluated by eval
with the same behaviour as the broken example.
即使它使用eval
,该行eval \$$cmd
也有相同的引用问题,因为\$$cmd
扩展到$cmd1
,然后用eval
与损坏的示例相同的行为对其进行评估。
The argument to eval
must be the actual command, not the expression $cmd1
. This can be done using variable indirection: eval "${!cmd}"
.
的参数eval
必须是实际的命令,而不是表达式$cmd1
。这可以使用变量间接完成:eval "${!cmd}"
。
When running this through SSH there is no need for the eval
because the remote shell also performs quote removal.
当通过 SSH 运行时,不需要 ,eval
因为远程 shell 也会执行引用删除。
So here is the fixed loop:
所以这是固定循环:
for cmd in cmd1 cmd2 ; do
eval "${!cmd}"
ssh server1 "${!cmd}"
done
An alternative to indirection is to iterate over the values of cmd1
and cmd2
instead of their names:
间接的替代方法是迭代 和 的值cmd1
而cmd2
不是它们的名称:
for cmd in "$cmd1" "$cmd2" ; do
eval "$cmd"
ssh server1 "$cmd"
done
回答by Maxime Chéramy
I see two solutions, either you change your loop to:
我看到两种解决方案,要么将循环更改为:
for cmd in "$cmd1" "$cmd2" ; do
ssh server1 $cmd
done
or to:
或者:
for cmd in cmd1 cmd2 ; do
ssh server1 ${!cmd}
done
回答by anubhava
Instead of eval \$$cmd
you need to use:
而不是eval \$$cmd
你需要使用:
res=$(eval "$cmd")
ssh server1 "$res"