2010-07-06 9 views
1

J'écris un script pour exécuter des commandes CURL pour une entrée utilisateur donnée. Le script a plusieurs fonctions auxiliaires pour créer la liste des paramètres (arguments) qui seront éventuellement transmis à CURL.Bash, curl, eval et espace

Un exemple dépouillé, est la suivante:

#!/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 

Le script fonctionne très bien lorsque les paramètres d'entrée (chemin de fichier, etc ..) URL ont (cité) un espace blanc en eux. Cependant, lorsque les arguments censés être transmis en tant que HTTP Headers à CURL contiennent des espaces, le script échoue lamentablement.

Voici ce que j'ai essayé:

  1. Utilisez des guillemets simples autour de la valeur d'en-tête (par exemple '__ $ hdr'). Cependant, avec ceci la valeur qui est passée à CURL est:
    curl -v http://google.co.in -X GET -H 'x-madhurt-test:madh urt'
    , qui est traitée comme-par CURL et l'en-tête réel qui est envoyé est comme ceci:
    'x-madhurt-test:madh
  2. Double échapper la valeur d'en-tête (par exemple \\ "$ __ hdr \\ "), mais cela semble fonctionner aussi bien. Dans ce cas CURL obtient "urt" comme un paramètre distinct et le traite comme une URL
    curl: (6) Couldn't resolve host 'urt"'
  3. Echapper l'espace dans la valeur d'en-tête (c'est à dire utiliser "madh \ urt" au lieu de "madh urt"), mais cela s'avère être le même que l'option 2.

Est-ce que quelqu'un a des idées sur ce qui se passe mal ici?

+0

Pour votre information: Mon utilisation de eval pour la variable de retour provient de cet article: http://www.linuxjournal.com/content/return- values-bash-functions – madhurtanwani

Répondre

1

Ce code fonctionne mais il n'est pas destiné à être utilisé tel quel. Je l'affiche pour vous donner des idées sur la façon de procéder. Ils permettent de faire ce que vous voulez faire est d'utiliser un tableau. Malheureusement, Bash ne peut pas retourner des tableaux à partir de fonctions. Ce que vous devez probablement faire est d'utiliser un tableau global. Toutefois, le code ci-dessous crée une chaîne à partir d'une instruction declare et la transmet via votre variable indirecte. C'est un très mauvais kludge.

#!/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[@]}" 
+0

Merci pour le script Dennis. Je vais y aller à travers et comprendre. Pourriez-vous s'il vous plaît m'aider à comprendre pourquoi le code que j'ai écrit ne fonctionne pas comme je le devrais? Je veux comprendre le problème technique. Merci et appréciez votre temps pour répondre à cette queston !! – madhurtanwani

1

La réponse de Dennis est bonne, donc je vais me concentrer sur pourquoi votre code ne fonctionne pas. Utilisons une fonction Auxiliar pour montrer les arguments reçus par une fonction:

$ args() { for x in "[email protected]"; do echo $x; done } 
$ args 1 '2 b' 3 
1 
2 b 
3 

Ok, comme prévu les guillemets sont uniquement utilisés pour délimiter des arguments. Mais maintenant, utilisons une variable comme vous l'avez fait:

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

Bash développe la variable et la fonction (ou la commande) obtient les guillemets. Ce n'est pas ce que tu voulais, bien sûr.

Solution1: Utilisez eval pour réinterpréter les devis. Solution2: Utilisez un tableau et développez-le avec "$ {MYARRAY [@]}" comme l'a montré Dennis.

idées Plus: une technique que je l'ai parfois utilisé fait l'eval extérieur:

$ eval "$(create_args_list VARNAME)" 

Dans ce cas otherfun renverrait une chaîne qui, quand evaled, créerait une variable avec le nom VARNAME (qui peut être même local). Cette variable (ou les variables, si nécessaire) peut être une chaîne ou un tableau.Encore une fois, j'utiliser un tableau pour pouvoir être facilement utilisé par la suite:

$ curl "${VARNAME[@]}" 
+0

Merci pour l'explication. Rend les choses claires !! – madhurtanwani