Der wahrscheinlich einfachste und sicherste Weg in BASH 3 und höher ist:
var="string to split"
read -ra arr <<<"$var"
(Wo arr
ist das Array, das die geteilten Teile des Strings aufnimmt?) oder wenn die Eingabe möglicherweise Zeilenumbrüche enthält und Sie mehr als nur die erste Zeile möchten:
var="string to split"
read -ra arr -d '' <<<"$var"
(Bitte beachten Sie das Leerzeichen in -d ''
, es kann nicht weggelassen werden), aber dies kann zu einem unerwarteten Zeilenumbruch führen <<<"$var"
(da dies implizit einen LF am Ende hinzufügt).
Beispiel:
touch NOPE
var="* a *"
read -ra arr <<<"$var"
for a in "${arr[@]}"; do echo "[$a]"; done
Gibt das erwartete aus
[*]
[a]
[*]
da diese Lösung (im Gegensatz zu allen vorherigen Lösungen hier) nicht zu unerwartetem und oft unkontrollierbarem Shell-Globbing neigt.
Auch dies gibt Ihnen die volle Leistung von IFS, wie Sie wahrscheinlich wollen:
Beispiel:
IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd)
for a in "${arr[@]}"; do echo "[$a]"; done
Gibt so etwas aus wie:
[tino]
[x]
[1000]
[1000]
[Valentin Hilbig]
[/home/tino]
[/bin/bash]
Wie Sie sehen, können Räume auch auf diese Weise erhalten werden:
IFS=: read -ra arr <<<' split : this '
for a in "${arr[@]}"; do echo "[$a]"; done
Ausgänge
[ split ]
[ this ]
Bitte beachten Sie, dass der Umgang mit IFS
in BASH ein eigenständiges Thema ist. Machen Sie also Ihre Tests, einige interessante Themen dazu:
unset IFS
: Ignoriert Läufe von SPC, TAB, NL und startet und endet online
IFS=''
: Keine Feldtrennung, liest einfach alles
IFS=' '
: Läufe von SPC (und nur SPC)
Ein letztes Beispiel
var=$'\n\nthis is\n\n\na test\n\n'
IFS=$'\n' read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
Ausgänge
1 [this is]
2 [a test]
während
unset IFS
var=$'\n\nthis is\n\n\na test\n\n'
read -ra arr -d '' <<<"$var"
i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done
Ausgänge
1 [this]
2 [is]
3 [a]
4 [test]
Übrigens:
Wenn Sie nicht $'ANSI-ESCAPED-STRING'
daran gewöhnt sind, ist dies eine Zeitersparnis.
Wenn Sie nicht einschließen -r
(wie in read -a arr <<<"$var"
), wird beim Lesen ein Backslash ausgeführt. Dies bleibt als Übung für den Leser.
Zur zweiten Frage:
Um auf etwas in einer Zeichenfolge zu testen, halte ich mich normalerweise daran case
, da dies mehrere Fälle gleichzeitig prüfen kann (Hinweis: case führt nur die erste Übereinstimmung aus, wenn Sie mehrere case
Anweisungen verwenden müssen), und dies ist häufig der Fall (Wortspiel) beabsichtigt):
case "$var" in
'') empty_var;; # variable is empty
*' '*) have_space "$var";; # have SPC
*[[:space:]]*) have_whitespace "$var";; # have whitespaces like TAB
*[^-+.,A-Za-z0-9]*) have_nonalnum "$var";; # non-alphanum-chars found
*[-+.,]*) have_punctuation "$var";; # some punctuation chars found
*) default_case "$var";; # if all above does not match
esac
So können Sie den Rückgabewert so einstellen, dass nach SPC gesucht wird:
case "$var" in (*' '*) true;; (*) false;; esac
Warum case
? Da es normalerweise etwas besser lesbar ist als Regex-Sequenzen und dank Shell-Metazeichen 99% aller Anforderungen sehr gut erfüllt.