代码之家  ›  专栏  ›  技术社区  ›  madhurtanwani

Bash、curl、eval和空格

  •  1
  • madhurtanwani  · 技术社区  · 16 年前

    我正在编写一个脚本来为给定的用户输入执行CURL命令。脚本有多个helper函数来创建最终将传递给CURL的参数(参数)列表。

    一个简单的例子如下:

    #!/bin/bash
    function create_arg_list
    {
        # THIS HTTP HEADER VALUE COMES FROM THE USER and MAY CONTAIN SPACES
     local __hdr="x-madhurt-test:madh urt"
     local __params="http://google.co.in -X GET -H '$__hdr'"
    
     local __resultvar="$1"
     eval $__resultvar="\"$__params\""
     echo "params after eval : $__resultvar"
    }
    
    
    create_arg_list arg_list
    echo "params after eval in main code : $arg_list"
    
    echo "Running command : curl -v $arg_list"
    curl -v $arg_list
    

    以下是我尝试过的:

    1. 在标题值周围使用单引号(例如$\uhdr)。但是,通过此函数传递给CURL的值为:
      curl -v http://google.co.in -X GET -H 'x-madhurt-test:madh urt'
      'x-madhurt-test:madh
    2. 对标题值进行双转义(例如“\\”$\uhdr\\”),但这似乎也起作用。在本例中,CURL将“urt”作为一个单独的参数,并将其视为URL
      curl: (6) Couldn't resolve host 'urt"'

    2 回复  |  直到 16 年前
        1
  •  1
  •   Dennis Williamson    16 年前

    这段代码可以工作,但不打算按原样使用。我把它贴出来是想给你一些想法,让你知道如何继续下去。它们使你想做的事情工作的关键是使用数组。不幸的是,Bash无法从函数返回数组。您可能应该使用全局数组。但是,下面的代码从 declare 语句并将其传递给间接变量。这是一个严重的混乱。

    #!/bin/bash
    function create_arg_list
    {
        # THIS HTTP HEADER VALUE COMES FROM THE USER and MAY CONTAIN SPACES
     local __hdr="x-madhurt-test:madh urt"
     local __params="http://google.co.in -X GET -H"
     __params=($__params "$__hdr")
    
     local __resultvar="$1"
     eval $__resultvar=$(printf "%q" "$(declare -p __params)")
     echo "params after eval : $__resultvar"
    }
    
    create_arg_list arg_list
    echo "params after eval in main code : $arg_list"
    
    echo "Running command : curl -v $arg_list"
    
    eval $arg_list
    
    curl -v "${__params[@]}"
    
        2
  •  1
  •   tokland    16 年前

    丹尼斯的答案很好,所以我将重点讨论为什么你的代码不起作用。让我们使用辅助函数来显示函数接收的参数:

    $ args() { for x in "$@"; do echo $x; done }
    $ args 1 '2 b' 3
    1
    2 b
    3
    

    好的,正如预期的那样,引号仅用于分隔参数。但是现在让我们像你一样使用一个变量:

    $ var="1 '2 b' 3"
    $ args $var
    1
    '2
    b'
    3
    

    Bash展开变量,函数(或命令)得到引号。当然,那不是你想要的。

    $ eval args $var
    1
    2 b
    3
    

    解决方案2:使用数组并用“${MYARRAY[@]}”展开它,如Dennis所示。

    $ eval "$(create_args_list VARNAME)"
    

    在本例中,otherfun将返回一个字符串,当对其求值时,该字符串将创建一个名为VARNAME的变量(甚至可以是本地变量)。此变量(或变量,如果需要)可以是字符串或数组。同样,我会使用一个数组,以便以后可以方便地使用它:

    $ curl "${VARNAME[@]}"