Bash, curl, eval и пробелы - PullRequest
1 голос
/ 06 июля 2010

Я пишу скрипт для выполнения команд 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 <a href="http://google.co.in" rel="nofollow noreferrer">http://google.co.in</a> -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.

Есть ли у кого-то понимание того, что здесь происходит неправильно?

Ответы [ 2 ]

1 голос
/ 07 июля 2010

Ответ Денниса хорош, поэтому я сосредоточусь на том, почему ваш код не работает.Давайте использовать вспомогательную функцию, чтобы показать аргументы, полученные функцией:

$ 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 раскрывает переменную, и функция (или команда) получает кавычки.Конечно, это не то, что вы хотели.

Solution1: используйте eval для повторной интерпретации кавычек.

$ eval args $var
1
2 b
3

Solution2: используйте массив и разверните его с помощью $} "как показал Деннис.

Больше идей: техника, которую я иногда использовал, выполняет eval снаружи:

$ eval "$(create_args_list VARNAME)"

В этом случае otherfun вернет строку, которая, если ее уклонитьсоздаст переменную с именем VARNAME (которая может быть даже локальной).Эта переменная (или переменные, если необходимо) может быть строкой или массивом.Опять же, я бы использовал массив, чтобы потом его можно было легко использовать:

$ curl "${VARNAME[@]}"
1 голос
/ 06 июля 2010

Этот код работает, но он не предназначен для использования как есть.Я публикую его, чтобы дать вам несколько идей о том, как вы можете поступить.Ключ к созданию того, что вы хотите сделать - это использовать массив.К сожалению, 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[@]}"
...