尝试在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
我已经考虑了我必须考虑的变体,例如循环内的ssh等,因为我的脚本需要这些变体。我认为eval是正确的方向,但是命令中的引号被解释的方式是错误的。
答案 0 :(得分:5)
考虑这个破碎的例子:
$ cmd1="touch \"file with spaces\""
$ $cmd1
在$cmd1
展开之前处理报价,因此,这将创建三个名为"file
,with
和spaces"
的文件,而不是一个文件。在扩展后,可以使用eval $cmd
强制删除引用。
即使它使用eval
,行eval \$$cmd
也有相同的引用问题,因为\$$cmd
扩展为$cmd1
,然后由eval
进行评估与破碎的例子相同的行为。
eval
的参数必须是实际命令,而不是表达式$cmd1
。这可以使用变量间接来完成:eval "${!cmd}"
。
通过SSH运行时,不需要eval
,因为远程shell也会执行引用删除。
所以这是固定循环:
for cmd in cmd1 cmd2 ; do
eval "${!cmd}"
ssh server1 "${!cmd}"
done
间接的替代方法是迭代cmd1
和cmd2
的值而不是它们的名称:
for cmd in "$cmd1" "$cmd2" ; do
eval "$cmd"
ssh server1 "$cmd"
done
答案 1 :(得分:1)
我看到两个解决方案,要么将循环更改为:
for cmd in "$cmd1" "$cmd2" ; do
ssh server1 $cmd
done
或者:
for cmd in cmd1 cmd2 ; do
ssh server1 ${!cmd}
done
答案 2 :(得分:0)
而不是eval \$$cmd
,您需要使用:
res=$(eval "$cmd")
ssh server1 "$res"