在bash中从变量执行for循环中的命令

del*_*ard 1 variables bash shell loops eval

尝试在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
Run Code Online (Sandbox Code Playgroud)

我已经考虑了我必须考虑的变体,例如循环中的ssh等,因为我的脚本需要这些变体.我认为eval是正确的方向,但是命令中的引号被解释的方式是错误的.

tom*_*tom 5

考虑这个破碎的例子:

$ cmd1="touch \"file with spaces\""
$ $cmd1
Run Code Online (Sandbox Code Playgroud)

引用之前处理$cmd1扩大,所以不是一个文件,这将创建三个文件叫"file,withspaces".可以使用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
Run Code Online (Sandbox Code Playgroud)

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

for cmd in "$cmd1" "$cmd2" ; do
    eval "$cmd"
    ssh server1 "$cmd"
done
Run Code Online (Sandbox Code Playgroud)