20

在 shell 脚本(在 .zshrc 中)中,我试图执行一个命令,该命令作为字符串存储在另一个变量中。网络上的各种消息来源说这是可能的,但我没有得到我期望的行为。可能~是命令开头的 ,也可能是使用sudo,我不确定。有任何想法吗?谢谢

function update_install()
{
    # builds up a command as a string...
    local install_cmd="$(make_install_command $@)"
    # At this point the command as a string looks like: "sudo ~some_server/bin/do_install arg1 arg2"
    print "----------------------------------------------------------------------------"
    print "Will update install"
    print "With command: ${install_cmd}"
    print "----------------------------------------------------------------------------"
    echo "trying backticks"
    `${install_cmd}`
    echo "Trying \$()"
    $(${install_cmd})
    echo "Trying \$="
    $=install_cmd
}

输出:

Will update install
With command: sudo ~some_server/bin/do_install arg1 arg2

trying backticks
update_install:9: no such file or directory: sudo ~some_server/bin/do_install arg1 arg2
Trying $()
update_install:11: no such file or directory: sudo ~some_server/bin/do_install arg1 arg2
Trying $=
sudo ~some_server/bin/do_install arg1 arg2: command not found
4

3 回答 3

32

使用eval

eval ${install_cmd}
于 2012-12-02T00:27:22.450 回答
11

正如第 3.1 节中所解释的那样“为什么$varwherevar="foo bar"不符合我的预期?” 在 Z-Shell FAQ中,您可以使用shwordsplitshell 选项告诉zsh您希望它用空格分隔变量并将它们视为多个单词。同一页面还讨论了您可能要考虑的替代方案。

于 2012-12-02T00:32:58.760 回答
0

我相信您在这里有两个问题 - 第一个是您install_cmd被解释为单个字符串,而不是sudo带有 3 个参数的命令 ( )。

您的最后一次尝试$=install_cmd实际上确实正确地解决了该问题(尽管我会这样写${=install_cmd}),但是您遇到了第二个问题:~some_server/bin/do_install不是已知命令。这是因为出于安全原因,sudo它不会像您想要的那样解释;~它需要使用 shell 来评估它的参数(或者为 做一些特殊情况~,这实际上与sudo' 无关),这会打开一整罐蠕虫,可以理解的是,sudo它会尽力避免。

这也是它起作用的原因eval ${install_cmd}- 因为这实际上将整个字符串视为要评估的东西,可能包含多个命令(例如,如果install_cmd包含echo foo; sudo rm -rf /它会很乐意擦除您的系统)。

您必须决定是否要install_cmd允许完整的 shell 语义,包括变量插值、路径扩展、多个命令等,或者是否应该只扩展单词并将它们作为单个命令运行。

于 2021-12-20T17:31:39.907 回答