【问题标题】:Bash, curl, eval and whitespaceBash、curl、eval 和空格
【发布时间】:2011-03-12 09:13:59
【问题描述】:

我正在编写一个脚本来为给定的用户输入执行 CURL 命令。该脚本有多个帮助函数来创建最终将传递给 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

当输入参数(文件路径、url 等)中包含(引用的)空格时,该脚本运行良好。但是,当应该作为 HTTP 标头传递给 CURL 的参数包含空格时,脚本会惨遭失败。

这是我尝试过的:

  1. 在标头值周围使用单引号(例如“$__hdr”)。但是,这样传递给 CURL 的值是:
    curl -v http://google.co.in -X GET -H 'x-madhurt-test:madh urt'
    ,CURL 将其视为发送的实际标头是这样的:
    'x-madhurt-test:madh
  2. 双重转义标头值(例如 \\"$__hdr\\"),但这似乎也有效。在这种情况下,CURL 将“urt”作为单独的参数并将其视为 URL
    curl: (6) Couldn't resolve host 'urt"'
  3. 转义标头值中的空格(即使用“madh\ urt”而不是“madh urt”),但这与选项 2 相同。

有人对这里发生的问题有见解吗?

【问题讨论】:

标签: bash scripting curl eval whitespace


【解决方案1】:

Dennis 的回答很好,所以我将重点介绍为什么您的代码不起作用。让我们使用辅助函数来显示函数接收到的参数:

$ 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 扩展变量并且函数(或命令)获取引号。当然,这不是你想要的。

解决方案 1:使用 eval 重新解释引号。

$ eval args $var
1
2 b
3

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

更多想法:我有时使用的一种技术是在外部进行评估:

$ eval "$(create_args_list VARNAME)"

在这种情况下,otherfun 将返回一个字符串,该字符串在评估时会创建一个名为 VARNAME 的变量(甚至可以是本地变量)。此变量(或变量,如果需要)可以是字符串或数组。同样,我会使用一个数组,以便以后可以轻松使用它:

$ curl "${VARNAME[@]}"

【讨论】:

    【解决方案2】:

    此代码有效,但不打算按原样使用。我发布它是为了给你一些关于如何进行的想法。它们使您想做的工作的关键是使用数组。不幸的是,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[@]}"
    

    【讨论】:

    • 感谢丹尼斯的剧本。我会通过它并理解。你能帮我理解为什么我写的代码不能正常工作吗?我想了解那里的故障/技术问题。感谢并感谢您抽出宝贵时间回答这个问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 2018-09-26
    相关资源
    最近更新 更多