2

尝试运行在 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 是正确的方向,但是命令中的引号被解释的方式是错误的。

4

3 回答 3

5

考虑这个破碎的例子:

$ cmd1="touch \"file with spaces\""
$ $cmd1

引用是在展开之前处理的,因此这将创建三个名为、和$cmd1的文件,而不是一个文件。可以在展开后使用强制移除引号。"filewithspaces"eval $cmd

即使它使用eval,该行eval \$$cmd也具有相同的引用问题,因为\$$cmd扩展为$cmd1,然后eval使用与损坏示例相同的行为对其进行评估。

to 的参数eval必须是实际的命令,而不是表达式$cmd1。这可以使用变量间接来完成:eval "${!cmd}".

当通过 SSH 运行时,不需要 ,eval因为远程 shell 也会执行引号删除。

所以这里是固定循环:

for cmd in cmd1 cmd2 ; do
    eval "${!cmd}"
    ssh server1 "${!cmd}"
done

间接的替代方法是迭代 和 的值cmd1cmd2不是它们的名称:

for cmd in "$cmd1" "$cmd2" ; do
    eval "$cmd"
    ssh server1 "$cmd"
done
于 2013-11-08T11:51:42.827 回答
1

我看到了两种解决方案,要么将循环更改为:

for cmd in "$cmd1" "$cmd2" ; do
    ssh server1 $cmd
done

或者:

for cmd in cmd1 cmd2 ; do
    ssh server1 ${!cmd}
done
于 2013-11-08T11:19:29.507 回答
0

而不是eval \$$cmd你需要使用:

res=$(eval "$cmd")
ssh server1 "$res"
于 2013-11-08T11:15:37.413 回答