Nejjednodušším řešením je vytvořit pole z citovaných argumentů, které pak můžete přepínat, pokud chcete, nebo je předat přímo příkazu.
eval "array=($string)"
for arg in "${array[@]}"; do echo "$arg"; done
p.s. Prosím komentujte, pokud najdete jednodušší způsob bez eval
.
Upravit:
Na základě odpovědi @Hubbitus máme plně dezinfikovanou a správně citovanou verzi. Poznámka:Toto je přehnané a ve skutečnosti zanechá další zpětná lomítka ve dvojitých nebo jednoduchých uvozovkách před většinou interpunkce, ale je nezranitelný vůči útoku.
declare -a "array=($( echo "$string" | sed 's/[][`[email protected]#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"
Nechávám to na zainteresovaném čtenáři, aby si upravil, jak uzná za vhodné http://ideone.com/FUTHhj
Když jsem viděl odpověď Davida Postilla, pomyslel jsem si „musí existovat jednodušší řešení“. Po nějakém experimentování jsem našel následující díla:-
string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo $string
eval 'for word in '$string'; do echo $word; done'
To funguje, protože eval
rozšíří řádek (odstraní uvozovky a rozšíří string
) před provedením výsledného řádku (což je vložená odpověď):
for word in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $word; done
Alternativa, která se rozšiřuje na stejný řádek, je:
eval "for word in $string; do echo \$word; done"
Zde string
je rozšířen v uvozovkách, ale $
musí být escapováno, takže word
není rozbalen před provedením řádku (v jiné formě má použití jednoduchých uvozovek stejný účinek). Výsledky jsou:-
[~/]$ 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
Jak to udělám?
$ 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
Co mám dělat, když je můj řetězec v bash
proměnná?
Jednoduchý přístup pomocí bash
string tokenizer nebude fungovat, protože se rozděluje na každé místo, nejen na ty mimo uvozovky:
[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"
Chcete-li to obejít, následující skript shellu (splitstring.sh) ukazuje jeden přístup:
#! /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
Výstup:
$ ./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
Zdroj:StackOverflow odpověď Rozdělit řetězec pouze na mezery, které jsou mimo uvozovky podle choroby. Skript byl upraven tak, aby odpovídal požadavkům otázky.