Wie kann ich die Ausgabe eines Befehls aufteilen und das Ergebnis mit nur einem einzigen Ausdruck einem Array zuweisen?

Wie kann ich die Ausgabe eines Befehls aufteilen und das Ergebnis mit nur einem einzigen Ausdruck einem Array zuweisen?

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 fooist 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 fooAusgabe 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 $IFSauf 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[@]}"

verwandte Informationen