Hinweis:Ich habe die Antworten auf andere ähnliche Fragen gelesen (Wie teilt man die Ausgabe auf und speichert sie in einem Array?,So teilen Sie einen String in Bash in ein Array auf), aber keine davon beantwortet die konkrete Frage, die ich hier stelle.
Angenommen, die Ausgabe eines Befehls foo
ist eine einzelne Zeile, die aus 10 durch Tabulatoren getrennten Feldern besteht. Dann
tmpvar=$( foo )
fields=( ${(ps:\t:)tmpvar} )
echo $#fields
# 10
Q:Wie kann ich die gleiche Aufteilung der foo
Ausgabe von auf Registerkarten erreichen, ohne dass eine Zwischenzuweisung an erforderlich ist tmpvar
?
FWIW, das funktioniert nicht:
fields=( ${(ps:\t:)$( foo )} )
echo $#fields
# 1
Antwort1
$ printf '<%s>\n' "${(@ps:\t:)$(printf 'foo bar\t\tbaz')}"
<foo bar>
<>
<baz>
Oder wenn Sie die leeren Elemente wie in Ihrem Tempvar-Ansatz unterdrücken möchten:
$ printf '<%s>\n' ${(ps:\t:)"$(printf 'foo bar\t\tbaz')"}
<foo bar>
<baz>
Mit anderen Worten, Sie müssen die Befehlssubstitution in Anführungszeichen setzen. Andernfalls s:\t:
gilt dies für die Verbindung (mit dem ersten Zeichen von $IFS
) der Felder, die sich aus der $IFS
-Aufteilung der Befehlssubstitution ergeben.
Alternativ können Sie den Wert $IFS
auf eine leere Zeichenfolge oder auf ein einzelnes Zeichen setzen, das kein Leerzeichen ist.
$ (IFS=; printf '<%s>\n' ${(ps:\t:)$(printf 'foo bar\t\tbaz')})
<foo bar>
<baz>
Antwort2
Sie sollten $( foo ) in Anführungszeichen setzen.
fields=( ${(ps:\t:)"$( foo )"} )
echo $#fields
Sie findenhier ein paar nette Beispiele
Antwort3
IFS=" "; set -f
a=( $(echo -e "a b\tc d") )
printf '<%s>\n' "size=${#a[@]}" "${a[@]}"