2017-03-10 3 views
0

Comme indiqué ci-dessous, la substitution de commande modifie l'interprétation des arguments de ligne de commande entre guillemets. Qu'est-ce qui se passe sous le capot, et y a-t-il une solution de contournement?La commande-substitution interrompt les arguments avec des espaces

$ cat dumpargs.sh 
#! /usr/bin/env bash 
for i in "[email protected]" 
    { 
    echo "$i" 
    } 

$ cat testfile.txt 
'1 space' '2 space' 

$ ./dumpargs.sh $(cat testfile.txt) ## produced undesired output 
'1 
space' 
'2 
space' 

$ ./dumpargs.sh '1 space' '2 space' ## produces desired output 
1 space 
2 space 
+0

http://shellcheck.net/ aurait attrapé votre problème (le manque de citations menant à la fente de chaîne) pour vous. Bien que l'attente que les citations * littérales * (qui n'affectent pas le fractionnement des chaînes) soient traitées comme des citations * syntaxiques * (ce qui est le cas) est peut-être un problème plus important. –

+0

Ceci est également très proche de [BashFAQ # 50] (http://mywiki.wooledge.org/BashFAQ/050). –

+1

Réponse courte, utilisez 'xargs':' cat testfile.txt | xargs./Dumpargs.sh' – nobar

Répondre

2

Lorsque vous écrivez ./dumpargs.sh '1 space' '2 space' sur la ligne de commande, le shell interprète les guillemets simples avant de passer des arguments au script. L'argument n ° 1 aura la valeur 1 space, l'argument n ° 2 aura la valeur 2 space. Les guillemets simples ne font pas partie des valeurs. Lorsque vous écrivez ./dumpargs.sh $(cat testfile.txt), , le shell n'essaiera pas d'interpréter le contenu de testfile.txt. Le shell interprète uniquement le texte réel entré sur la ligne de commande. Le contenu substitué comme cet exemple, ou par exemple les valeurs de variables ne sont pas interprétées, mais utilisées littéralement. Enfin, l'interpréteur exécute la division de mots sur la chaîne sur la ligne de commande, en utilisant les délimiteurs dans IFS. Ainsi, les guillemets simples seront utilisés littéralement, et le contenu est simplement divisé par des espaces.

Une solution possible consiste à stocker un argument par ligne, sans les guillemets simples et faire dumpargs.sh prennent les arguments de la sortie standard:

while read -r line; do 
    echo "$line" 
done 

Vous pouvez l'appeler avec ./dumpargs.sh < testfile.txt.

+0

Votre solution de contournement n'est pas ce que je cherchais, mais j'apprécie les commentaires sur les différences dans la façon dont les choses sont interprétées sous les différents usages. Tout ce qui concerne la manipulation des cordes Bash me fait me gratter la tête, et cela apporte un peu de clarté. – nobar