J'ai un script wrapper qui fait du travail et passe ensuite les paramètres d'origine à un autre outil:
#!/bin/bash
# ...
other_tool -a -b "$@"
Cela fonctionne très bien, sauf si «l'autre outil» est exécuté dans un sous-shell:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Si j'appelle mon script wrapper comme ceci:
wrapper.sh -x "blah blup"
puis, seul le premier argument d'origine (-x) est remis à "other_tool". En réalité, je ne crée pas de sous-shell, mais passe les arguments d'origine à un shell sur un téléphone Android, ce qui ne devrait pas faire de différence:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Aucune des solutions ne fonctionne bien. Passez simplement x / \ \ \ "b \" / aaaaa / \ 'xxx \ yyyy \' / zz \ "offf \" comme paramètre et ils échoueront.
Voici un emballage simple qui gère chaque cas. Notez comment il échappe deux fois à chaque argument.
la source
Remplacez
$@
par$*
. J'ai fait un petit test local et ça marche dans mon cas.Enregistrer sous
test.sh
et le rendre exécutable donneIl y a une différence subtile entre
$*
et$@
, comme vous pouvez le voir. Voir par exemple http://ss64.com/bash/syntax-parameters.htmlPour la question de suivi dans les commentaires: vous devez échapper par exemple un espace blanc "deux fois" pour passer une chaîne avec un séparateur comme argument combiné, par exemple avec
test.sh
modifié à unwc
wrapper:Cela marche:
mais:
la source
wrapper.sh -x "blah blup"
le sous-shell obtient TROIS paramètres (-x, blah, blup) au lieu de DEUX (-x, "blah blup")"Blah\ blup"
. Essayez-le et voyez si cela fonctionne.Il échoue parce que vous contraignez un tableau (les paramètres positionnels) dans une chaîne.
"$@"
est magique car il vous donne chaque paramètre séparé comme une chaîne correctement citée. L'ajout de texte supplémentaire brise la magie:"blah $@"
n'est qu'une seule chaîne.Cela peut vous rapprocher:
Bien sûr, tout paramètre contenant une seule citation causera des problèmes.
la source
Ok, plus d'explications:
la source
J'ai essayé de nombreuses solutions différentes, une bonne ressource comprenant des informations de base et des alternatives est par exemple BashFAQ / 096 sur le wiki de Greg (aka. GreyCat) . Au total, j'ai trouvé que les deux suivants étaient les plus lisibles (parmi ceux qui fonctionnent):
Depuis Bash 4.4 (pour autant que je sache d'après les NOUVELLES ), il est possible d'utiliser l' expansion des paramètres
@Q
comme ceci:Notez que j'utilise
$*
ici au lieu de$@
parce que vous voulez"other_tool -a -b ${*@Q}"
être une seule chaîne au lieu d'une chaîne par argument passé.Si vous voulez faire de même avec une variable de tableau bash, vous aurez besoin de la syntaxe
${ARRAY[*]@Q}
(entre guillemets).Si vous n'avez pas Bash 4.4 ou version ultérieure disponible ou n'êtes pas sûr, c'est ma solution préférée:
Notez que vous devez utiliser ici à la
"$@"
place de$@
ou"$*"
ou$*
parce que vous ne voulez pas que les mots soient séparés dans les arguments, donc les variantes sans guillemets ne peuvent pas être utilisées, et vous voulez que le nombre d'arguments soit conservé, donc"$*"
ne peut pas être utilisé comme il se joindrait tous les arguments d'une seule chaîne. La fonction renvoie ensuite tous les arguments dans une seule chaîne.Si vous ne vous souciez pas de l'espace supplémentaire devant le premier argument, vous pouvez remplacer la
printf
chaîne de format par" %q"
et supprimer laseparator
variable. Ou vous pouvez utiliser la réponse à une ligne de Gordon Davissons .Ces solutions fonctionnent avec tous les cas que je pourrais trouver, en particulier:
escapeBashArgs
→ rienescapeBashArgs "" ""
→'' ''
escapeBashArgs " " " "
→' ' ' '
ou\ \ \ \ \
( le dernier espace est consommé par le rendu de ce site )escapeBashArgs "a b" c\ d "arg with newline"
→'a b' 'c d' $'arg with\nnewline'
oua\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( le saut de ligne est entrewith
etnewline
, sur d'autres positions, c'est à cause du retour à la ligne sur ce site )escapeBashArgs '$"'\''({:})'
→'$"'\''({:})'
ou\$\"\'\(\{:\}\)
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
oux/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Testé avec la version GNU bash 5.0.3 (1).)
la source
la source