110 votes

Comment conserver les citations dans les arguments de Bash ?

J'ai un Bash script où je veux garder les guillemets dans les arguments passés.

Ejemplo:

./test.sh this is "some test"

je veux ensuite utiliser ces arguments, et les réutiliser, en incluant des guillemets autour de toute la liste des arguments.

J'ai essayé d'utiliser \"$@\" mais cela supprime les guillemets à l'intérieur de la liste.

Comment puis-je y parvenir ?

13voto

Gary S. Weaver Points 4034

Comme Tom Hale l'a dit, une façon de le faire est avec printf en utilisant %q à l'apostrophe.

Par exemple :

send_all_args.sh

#!/bin/bash
if [ "$#" -lt 1 ]; then
 quoted_args=""
else
 quoted_args="$(printf " %q" "${@}")"
fi

bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_args}"

send_fewer_args.sh

#!/bin/bash
if [ "$#" -lt 2 ]; then
 quoted_last_args=""
else
 quoted_last_args="$(printf " %q" "${@:2}")"
fi

bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_last_args}"

receiver.sh

#!/bin/bash
for arg in "$@"; do
  echo "$arg"
done

Exemple d'utilisation :

$ ./send_all_args.sh
$ ./send_all_args.sh a b
a
b
$ ./send_all_args.sh "a' b" 'c "e '
a' b
c "e 
$ ./send_fewer_args.sh
$ ./send_fewer_args.sh a
$ ./send_fewer_args.sh a b
b
$ ./send_fewer_args.sh "a' b" 'c "e '
c "e 
$ ./send_fewer_args.sh "a' b" 'c "e ' 'f " g'
c "e 
f " g

6voto

JohnMudd Points 3196

Modifié démolir pour utiliser un tableau.

printargs() { printf "'%s' " "$@"; echo; };  # http://superuser.com/a/361133/126847

C=()
for i in "$@"; do
    C+=("$i")  # Need quotes here to append as a single array element.
done

printargs "${C[@]}"  # Pass array to a program as a list of arguments.

6voto

Gus Neves Points 430

Mon problème était similaire et j'ai utilisé des idées mixtes postées ici.

Nous avons un serveur avec un script qui envoie des e-mails. Et puis nous avons un deuxième serveur qui se connecte au 1er serveur via SSH et l'exécute.

Le nom script est le même sur les deux serveurs et les deux sont en fait exécutés via un bash script.

Sur le serveur 1 (local) bash script nous avons juste :

/usr/bin/php /usr/local/myscript/myscript.php "$@"

Celui-ci réside sur /usr/local/bin/myscript et est appelé par le serveur distant. Cela fonctionne bien même pour les arguments contenant des espaces.

Mais alors, sur le serveur distant, nous ne pouvons pas utiliser la même logique car le premier serveur ne recevra pas les citations de "$@" . J'ai utilisé les idées de JohnMudd et de Dennis Williamson pour recréer le tableau des options et des paramètres avec les guillemets. J'aime l'idée d'ajouter les guillemets échappés uniquement lorsque l'élément contient des espaces.

Donc le script distant s'exécute avec :

CSMOPTS=()
whitespace="[[:space:]]"
for i in "$@"
do
    if [[ $i =~ $whitespace ]]
    then
        CSMOPTS+=(\"$i\")
    else
        CSMOPTS+=($i)
    fi
done

/usr/bin/ssh "$USER@$SERVER" "/usr/local/bin/myscript ${CSMOPTS[@]}"

Notez que j'utilise "${CSMOPTS[@]}" pour passer le tableau des options au serveur distant.

Merci à tous ceux qui ont posté ici ! Ça m'a vraiment aidé !)

6voto

FrameGrace Points 239

Il suffit d'utiliser :

"${@}"

Par exemple :

# cat t2.sh
for I in "${@}"
do
   echo "Param: $I"
done
# cat t1.sh
./t2.sh "${@}"

# ./t1.sh "This is a test" "This is another line" a b "and also c"
Param: This is a test
Param: This is another line
Param: a
Param: b
Param: and also c

4voto

mouviciel Points 36624

Les guillemets sont interprétés par bash et ne sont pas stockés dans les arguments de la ligne de commande ou les valeurs des variables.

Si vous voulez utiliser des arguments cités, vous devez les citer à chaque fois que vous les utilisez :

val="$3"
echo "Hello World" > "$val"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X