Bash,curl,eval和whitespace

时间:2010-07-06 15:20:31

标签: bash scripting curl eval whitespace

我正在编写一个脚本来执行给定用户输入的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

当输入参数(文件路径,网址等)中包含(引用)空格时,脚本运行良好。但是,当应该作为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相同。
  4. 有人对此处发生的错误有洞察力吗?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

丹尼斯的答案很好,所以我会专注于你的代码无效的原因。让我们使用辅助函数来显示函数接收的参数:

$ 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:

$ eval "$(create_args_list VARNAME)"

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

$ curl "${VARNAME[@]}"