web-dev-qa-db-fra.com

Script bash pour recevoir et repasser les paramètres cités

J'essaie d'obtenir les paramètres cités d'un script bash pour être reçus en toute sécurité par un script imbriqué. Des idées?

test.sh

#!/bin/bash
echo $*
bash myecho.sh $*

myecho.sh

#!/bin/bash
 echo $1
 echo $2
 echo $3
 echo $4

Échantillon:

bash test.sh aaa bbb '"ccc ddd"'

Résultat:

aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"

Résultat recherché

aaa bbb "ccc ddd"
aaa
bbb
ccc ddd
94
chilltemp
#!/bin/bash
echo $*
bash myecho.sh "$@"

Notez que la construction "$ @" n'est pas spécifique à bash et devrait fonctionner avec n'importe quel shell POSIX (c'est le cas avec dash au moins). Notez également que compte tenu de la sortie souhaitée, vous n'avez pas du tout besoin du niveau supplémentaire de citation. C'EST À DIRE. il suffit d'appeler le script ci-dessus comme:

./test.sh 1 2 "3 4"
67
pixelbeat

Vous souhaitez utiliser "$ @" (dollar coté à) pour passer des paramètres à un indice. Ainsi ....

ls-color.sh:

#!/bin/bash
/bin/ls --color=auto "$@"    # passes though all CLI-args to 'ls'


Quant à savoir pourquoi .....

Depuis la page de manuel de Bash :

$* - S'étend aux paramètres de position, en commençant par un. Lorsque l'expansion se produit entre guillemets doubles, elle se développe en un seul mot avec la valeur de chaque paramètre séparée par le premier caractère de la variable spéciale IFS. C'est, "$*" est équivalent à "$1c$2c...", où c est le premier caractère de la valeur de la variable IFS. Si IFS n'est pas défini, les paramètres sont séparés par des espaces. Si IFS est nul, les paramètres sont joints sans séparateurs intermédiaires.

$@ - S'étend aux paramètres de position, en commençant par un. Lorsque l'expansion se produit entre guillemets doubles, chaque paramètre se développe dans un mot distinct. C'est, "$@" est équivalent à "$1" "$2" ... Si l'expansion entre guillemets se produit dans un mot, l'expansion du premier paramètre est jointe à la partie de début du mot d'origine et l'expansion du dernier paramètre est jointe à la dernière partie du mot d'origine. Lorsqu'il n'y a pas de paramètres de position, "$@" et $@ s'étendre à rien (c'est-à-dire qu'ils sont supprimés).


Configuration de quelques scripts de démonstration ...

echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh

"$@" - quoted-dollar-at est une transformation d'identité pour retransmettre les arguments à un sous-shell (~ 99 % du temps, c'est ce que vous vouliez faire):

./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2=            
  # $3= 'cc cc'
  # $4= "ddd ddd"

"$*" - étoile cotée écrase les arguments en une seule chaîne (~ 1% du temps, vous veulent réellement ce comportement, par exemple dans un conditionnel: if [[ -z "$*" ]]; then ...):

./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa  'cc cc' "ddd ddd"   
  # $2=                     
  # $3=             
  # $4=

$*/$@ - sans guillemets, les deux formulaires suppriment un niveau de citation et interprètent les espaces des chaînes sous-jacentes mais ignorent les caractères de citation (presque toujours, c'est une erreur):

./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc                  
  # $3= cc'
  # $4= "ddd

./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc
  # $3= cc'
  # $4= "ddd

Si vous voulez vous amuser, vous pouvez utiliser "$ @" pour imbriquer les choses aussi profondément que vous le souhaitez, en poussant et en sautant des éléments de la pile d'arguments si vous le souhaitez.

function identity() {
  "$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"
138
Dave Dopson