Bash et Double-Quotes passant à argv

J’ai réaffirmé cet exemple pour qu’il rest simple, mais ce que j’essaie de faire, c’est d’obtenir une chaîne de guillemets nestede sous la forme d’une seule valeur argv lorsque le shell bash l’exécute.

Voici l’exemple de script:

set -x command1="key1=value1 \"key2=value2 key3=value3\"" command2="keyA=valueA keyB=valueB keyC=valueC" echo $command1 echo $command2 

la sortie est:

 ++ command1='key1=value1 "key2=value2 key3=value3"' ++ command2='keyA=valueA keyB=valueB keyC=valueC' ++ echo key1=value1 '"key2=value2' 'key3=value3"' key1=value1 "key2=value2 key3=value3" ++ echo keyA=valueA keyB=valueB keyC=valueC keyA=valueA keyB=valueB keyC=valueC 

J’ai également testé que, lorsque vous faites tout sur la ligne de commande, le message de citation nested EST défini comme une seule valeur argv. c’est à dire

 prog.exe argument1 "argument2 argument3" argv[0] = prog.exe argv[1] = argument1 argv[2] = argument2 argument3 

En utilisant l’exemple ci-dessus:

 command1="key1=value1 \"key2=value2 key3=value3\"" 

L’erreur est, mon argv revient comme:

 arg[1] = echo arg[2] = key1=value1 arg[3] = "key2=value2 arg[4] = key3=value3" 

où je veux vraiment que ma valeur argv [3] soit “clé2 = valeur2 clé3 = valeur3”

J’ai remarqué que debug (set -x) affiche une seule citation aux points où mes arguments sont cassés, ce qui indique un peu qu’il réfléchit aux arguments à ces points de rupture … mais je ne suis pas sûr.

Une idée de ce qui se passe vraiment ici? Comment puis-je changer le script?

Merci d’avance.

En réalité, vos citations nestedes sont littérales et ne sont pas analysées par le shell dans des arguments distincts. Le meilleur moyen de gérer cela avec bash est d’utiliser un tableau au lieu d’une chaîne:

 args=('key1=value1', 'key2=value2 key3=value3') prog.exe "${args[@]}" 

La FAQ Bash50 contient quelques exemples supplémentaires et des cas d’utilisation de commandes dynamics.

Une sorte de “réponse” folle consiste à configurer IFS pour qu’il utilise une citation double (enregistrer / restaurer l’IFS d’origine):

 SAVED_IFS=$IFS IFS=$'\"' prog.exe $command1 IFS=$SAVED_IFS 

Cela illustre en quelque sorte le fractionnement des mots qui se produit sur des arguments sans guillemets mais n’affecte pas les variables ni le texte à l’intérieur des guillemets ".." . Le texte entre guillemets (après diverses extensions) est transmis au programme sous forme d’argument unique. Cependant, une variable nue $ command1 (non entre guillemets) subit un fractionnement de mot qui ne se soucie pas de " dans la variable (le prenant au sens littéral). Un bidouillage IFS stupide force le fractionnement de mot à " . Méfiez-vous également des espaces finaux à la fin de argv [1] qui apparaissent en raison de la division du mot à la " limite " .

La réponse de jordanm est bien meilleure pour une utilisation en production que la mienne 🙂 Le tableau est cité, c’est-à-dire que chaque élément du tableau est développé sous forme de chaîne individuelle et qu’aucune division de mot ne se produit par la suite. Ce qui est essentiel. Si elle n’est pas citée comme ${args[@]} , le mot serait divisé en trois arguments au lieu de deux.