【问题标题】:Execute command inside for loop from variable in bash从bash中的变量执行for循环内的命令
【发布时间】:2013-11-20 09:07:44
【问题描述】:

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

【问题讨论】:

标签: bash shell variables loops eval


【解决方案1】:

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

res=$(eval "$cmd")
ssh server1 "$res"

【讨论】:

  • 谢谢,但仍然无法正确插入命令中的字符串。
【解决方案2】:

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

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

或到:

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

【讨论】:

  • 似乎忽略了$($cmd),只是返回了一个登录信息。
  • 除非您设置 SSH-key,否则它会询问您的登录名和密码。
  • 抱歉,密钥已设置。它会提示我远程服务器,忽略我发送的命令。
  • 谢谢,汤姆在那个方面打败了你!但是谢谢;)
  • 是的,我第一次没看懂你的问题,很遗憾,因为我想到了${!cmd}。
【解决方案3】:

考虑这个损坏的例子:

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

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

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

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

【讨论】:

  • 不幸的是,正在运行的命令要求这些引号完整传递,因为它们构成参数的一部分(运行数据库查询的命令)。我并不是说“命令”是内置的,只是我想要运行的特定命令。
  • 完美运行!至少对于 ssh 到远程主机。我也只需要在本地运行。另外,如果您可以扩展正在做的事情,我将不胜感激。谢谢老兄!
  • @delronhubbard 我扩展了扩展:)
猜你喜欢
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 2014-08-27
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
相关资源
最近更新 更多