【问题标题】:Bash nested quotes and evalBash 嵌套引号和 eval
【发布时间】:2012-03-01 03:49:06
【问题描述】:

我在 bash 脚本中遇到嵌套引号问题

argv="su -c '$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
eval $argv

上面让我明白了

eval: line 162: unexpected EOF while looking for matching `''
eval: line 163: syntax error: unexpected end of file

【问题讨论】:

    标签: bash nested eval quotes


    【解决方案1】:

    Use an array instead.

    #!/bin/bash
    cmd=(echo "foo bar")
    "${cmd[@]}"
    

    【讨论】:

    • 我不确定您提供的链接是否讨论了您建议使用的 bash 数组。
    • @TomHale:我的回答有语法错误。
    【解决方案2】:
    argv="su -c \"$RVM_PATH wrapper $config_rvm \\\"$PASSENGER_RVM_BIN $command $options\\\"\" web"
    

    【讨论】:

      【解决方案3】:

      这是因为\' 在单引号字符串中没有任何特殊含义;它的意思只是“反斜杠,后跟字符串结尾”。

      一种选择是使用$'...' 而不是'...';这将让你使用反斜杠转义。它看起来像这样:

      argv="su -c $'$RVM_PATH wrapper $config_rvm \'$PASSENGER_RVM_BIN $command $options\'' web"
      

      不利的一面是,如果 $RVM_PATH$config_rvm 或任何其他变量可能包含反斜杠,那么它也可能被解释为引入反斜杠转义。

      【讨论】:

        【解决方案4】:

        eval 的通用解决方案,带有正确引用的参数

        下面的函数使用了shell自己的引用机制,这样我就不用担心如何正确引用东西了:

        function token_quote {
          local quoted=()
          for token; do
            quoted+=( "$(printf '%q' "$token")" )
          done
          printf '%s\n' "${quoted[*]}"
        }
        

        使用示例:

        $ token_quote token 'single token' token
        token single\ token token
        

        在上面,请注意single token 的空格被引用为\

        $ set $(token_quote token 'single token' token)
        $ eval printf '%s\\n' "$@"
        token
        single token
        token
        $
        

        这表明令牌确实是分开的。


        鉴于一些不受信任的用户输入:

        % input="Trying to hack you; date"
        

        构造一个命令来评估:

        % cmd=(echo "User gave:" "$input")
        

        评估它,看似正确引用:

        % eval "$(echo "${cmd[@]}")"
        User gave: Trying to hack you
        Thu Sep 27 20:41:31 +07 2018
        

        注意你被黑了。 date 被执行而不是被直接打印出来。

        改为token_quote():

        % eval "$(token_quote "${cmd[@]}")"
        User gave: Trying to hack you; date
        %
        

        eval 不是邪恶的——只是被误解了 :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-30
          • 2018-05-07
          • 2013-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-15
          • 2011-02-09
          相关资源
          最近更新 更多