La soluzione più semplice consiste nell'utilizzare la creazione di un array degli argomenti tra virgolette che puoi quindi ripetere se lo desideri o passare direttamente a un comando.
eval "array=($string)"
for arg in "${array[@]}"; do echo "$arg"; done
p.s. Commenta se trovi un modo più semplice senza eval
.
Modifica:
Basandoci sulla risposta di @Hubbitus, abbiamo una versione completamente ripulita e opportunamente citata. Nota:questo è eccessivo e in realtà lascerà barre rovesciate aggiuntive nelle sezioni con virgolette doppie o singole che precedono la maggior parte della punteggiatura, ma è invulnerabile agli attacchi.
declare -a "array=($( echo "$string" | sed 's/[][`[email protected]#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"
Lascio al lettore interessato di modificare come meglio crede http://ideone.com/FUTHhj
Quando ho visto la risposta di David Postill, ho pensato "ci deve essere una soluzione più semplice". Dopo alcuni esperimenti ho trovato i seguenti lavori:-
string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo $string
eval 'for word in '$string'; do echo $word; done'
Funziona perché eval
espande la riga (rimuovendo le virgolette ed espandendo string
) prima di eseguire la riga risultante (che è la risposta in linea):
for word in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $word; done
Un'alternativa che si espande alla stessa riga è:
eval "for word in $string; do echo \$word; done"
Qui string
è espanso tra virgolette doppie, ma il $
deve essere preceduto dall'escape in modo che word
in non espanso prima dell'esecuzione della riga (nell'altra forma l'uso delle virgolette singole ha lo stesso effetto). I risultati sono:-
[~/]$ 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
Come posso farlo?
$ 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
Cosa devo fare se la mia stringa è in un bash
variabile?
Il semplice approccio all'utilizzo del bash
string tokenizer non funzionerà, poiché si divide in ogni spazio, non solo in quelli al di fuori delle virgolette:
[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"
Per aggirare questo problema, il seguente script di shell (splitstring.sh) mostra un approccio:
#! /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
Uscita:
$ ./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
Fonte:risposta StackOverflow Dividi una stringa solo per spazi che sono al di fuori delle virgolette di choroba. Lo script è stato ottimizzato per soddisfare i requisiti della domanda.