La solution la plus simple consiste à créer un tableau des arguments entre guillemets que vous pouvez ensuite parcourir si vous le souhaitez ou passer directement à une commande.
eval "array=($string)"
for arg in "${array[@]}"; do echo "$arg"; done
p.s. Veuillez commenter si vous trouvez un moyen plus simple sans eval
.
Modifier :
En nous appuyant sur la réponse de @Hubbitus, nous avons une version entièrement épurée et correctement citée. Remarque :c'est exagéré et laissera en fait des barres obliques inverses supplémentaires dans les sections entre guillemets doubles ou simples précédant la plupart des signes de ponctuation, mais est invulnérable aux attaques.
declare -a "array=($( echo "$string" | sed 's/[][`[email protected]#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"
Je laisse au lecteur intéressé le soin de modifier à sa guise http://ideone.com/FUTHhj
Quand j'ai vu la réponse de David Postill, j'ai pensé "il doit y avoir une solution plus simple". Après quelques expérimentations, j'ai trouvé les œuvres suivantes :-
string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo $string
eval 'for word in '$string'; do echo $word; done'
Cela fonctionne car eval
développe la ligne (en supprimant les guillemets et en développant string
) avant d'exécuter la ligne résultante (qui est la réponse en ligne) :
for word in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $word; done
Une alternative qui se développe sur la même ligne est :
eval "for word in $string; do echo \$word; done"
Ici string
est développé entre guillemets, mais le $
doit être échappé pour que word
n'est pas développé avant l'exécution de la ligne (dans l'autre forme, l'utilisation de guillemets simples a le même effet). Les résultats sont :-
[~/]$ string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
[~/]$ echo $string
"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
[~/]$ eval 'for word in '$string'; do echo $word; done'
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
[~/]$ eval "for word in $string; do echo \$word; done"
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
Comment faire ?
$ for l in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $l; done
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
Que dois-je faire si ma chaîne est dans un bash
variable ?
L'approche simple de l'utilisation du bash
string tokenizer ne fonctionnera pas, car il se divise sur chaque espace et pas seulement sur ceux en dehors des guillemets :
[email protected] /f/test
$ cat ./test.sh
#! /bin/bash
string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
for word in $string; do echo "$word"; done
[email protected] /f/test
$ ./test.sh
"aString
that
may
haveSpaces
IN
IT"
bar
foo
"bamboo"
"bam
boo"
Pour contourner ce problème, le script shell suivant (splitstring.sh) montre une approche :
#! /bin/bash
string=$(cat <<'EOF'
"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
EOF
)
echo Source String: "$string"
results=()
result=''
inside=''
for (( i=0 ; i<${#string} ; i++ )) ; do
char=${string:i:1}
if [[ $inside ]] ; then
if [[ $char == \\ ]] ; then
if [[ $inside=='"' && ${string:i+1:1} == '"' ]] ; then
let i++
char=$inside
fi
elif [[ $char == $inside ]] ; then
inside=''
fi
else
if [[ $char == ["'"'"'] ]] ; then
inside=$char
elif [[ $char == ' ' ]] ; then
char=''
results+=("$result")
result=''
fi
fi
result+=$char
done
if [[ $inside ]] ; then
echo Error parsing "$result"
exit 1
fi
echo "Output strings:"
for r in "${results[@]}" ; do
echo "$r" | sed "s/\"//g"
done
Sortie :
$ ./splitstring.sh
Source String: "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
Output strings:
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
Source :StackOverflow answer Divisez une chaîne uniquement par des espaces qui sont en dehors des guillemets par choroba. Le script a été modifié pour correspondre aux exigences de la question.