Bourne / POSIX-ähnliche Shells haben einen split + glob-Operator und werden jedes Mal aufgerufen, wenn Sie eine Parametererweiterung ( $var
, $-
...), eine Befehlssubstitution ( $(...)
) oder eine arithmetische Erweiterung ( $((...))
) im Listenkontext nicht in Anführungszeichen setzen.
Eigentlich aufgerufen Sie es aus Versehen , wenn Sie tat for name in ${array[@]}
statt for name in "${array[@]}"
. (Beachten Sie, dass das versehentliche Aufrufen dieses Operators viele Fehler und Sicherheitslücken verursacht. )
Dieser Operator wird mit dem $IFS
speziellen Parameter (um anzugeben, auf welche Zeichen aufgeteilt werden soll (wobei darauf zu achten ist, dass Leerzeichen, Tabulator und Zeilenvorschub dort eine besondere Behandlung erfahren)) und der -f
Option zum Deaktivieren ( set -f
) oder Aktivieren ( set +f
) des glob
Teils konfiguriert .
Beachten Sie auch, dass das S
in $IFS
ursprünglich (in der Bourne-Shell, von der es $IFS
stammt) für Separator war, in POSIX-Shells die Zeichen in $IFS
eher als Begrenzer oder Abschlusszeichen zu sehen sind (siehe unten für ein Beispiel).
Also aufteilen _
:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
array=($string) # invoke the split+glob operator
for i in "${array[@]}"; do # loop over the array elements.
Um die Unterscheidung zwischen Trennzeichen und Trennzeichen zu sehen , probieren Sie Folgendes aus:
string='var1_var2_'
Das wird spaltete es in var1
und var2
nur (kein zusätzliches leeres Element).
Um es ähnlich wie JavaScript zu machen split()
, benötigen Sie einen zusätzlichen Schritt:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
temp=${string}_ # add an extra delimiter
array=($temp) # invoke the split+glob operator
(Beachten Sie, dass ein leeres Element wie bei JavaScript $string
in 1 (nicht in 0split()
) aufgeteilt wird.)
Um zu sehen, welche Sonderbehandlungen Tab, Space und Newline erhalten, vergleichen Sie:
IFS=' '; string=' var1 var2 '
(wo bekommt man var1
und var2
) mit
IFS='_'; string='_var1__var2__'
wo Sie bekommen: ''
, var1
, ''
, var2
, ''
.
Beachten Sie, dass die zsh
Shell diesen split + glob-Operator nur implizit aufruft, wenn er in sh
oder ksh
emuliert ist. Dort müssen Sie es explizit aufrufen. $=string
für den aufgeteilten Teil, $~string
für den Glob-Teil ( $=~string
für beide), und es hat auch einen aufgeteilten Operator, in dem Sie das Trennzeichen angeben können:
array=(${(s:_:)string})
oder um die leeren Elemente zu erhalten:
array=("${(@s:_:)string}")
Beachten Sie, dass es s
zum Teilen , nicht zum Abgrenzen (auch bei $IFS
einer bekannten POSIX-Abweichung von zsh
) gibt. Es unterscheidet sich von JavaScript split()
darin, dass eine leere Zeichenfolge in ein 0-Element (nicht in ein 1-Element) aufgeteilt wird.
Ein bemerkenswerter Unterschied zu $IFS
-splitting besteht darin, dass ${(s:abc:)string}
sich die abc
Zeichenfolge aufteilt , während sich mit IFS=abc
, das aufteilen würde a
, b
oder c
.
Mit zsh
und ksh93
kann die Sonderbehandlung, die Leerzeichen, Tabulatoren oder Zeilenumbrüche erhalten, durch Verdoppeln entfernt werden $IFS
.
Als historische Notiz hat die Bourne-Shell (die Vorgänger- oder die moderne POSIX-Shell) immer die leeren Elemente entfernt. Es hatte auch eine Reihe von Fehlern im Zusammenhang mit der Aufteilung und Erweiterung von $ @ mit Nicht-Standardwerten von $IFS
. Zum Beispiel IFS=_; set -f; set -- $@
wäre nicht gleichbedeutend mit IFS=_; set -f; set -- $1 $2 $3...
.
Aufteilen auf reguläre Ausdrücke
Wenn Sie sich etwas näher mit JavaScript befassen möchten split()
, das sich in reguläre Ausdrücke aufteilen lässt, müssen Sie sich auf externe Dienstprogramme verlassen.
Hat im POSIX-Werkzeugkasten awk
einen split
Operator, der auf erweiterte reguläre Ausdrücke aufgeteilt werden kann (dies ist mehr oder weniger eine Teilmenge der von JavaScript unterstützten Perl-ähnlichen regulären Ausdrücke).
split() {
awk -v q="'" '
function quote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(ARGV[1], a, ARGV[2])
for (i = 1; i <= n; i++) printf " %s", quote(a[i])
exit
}' "$@"
}
string=a__b_+c
eval "array=($(split "$string" '[_+]+'))"
Die zsh
Shell verfügt über eine integrierte Unterstützung für Perl-kompatible reguläre Ausdrücke (in ihrem zsh/pcre
Modul). Die Verwendung dieser Funktion zum Teilen einer Zeichenfolge ist jedoch relativ umständlich.
shell
Sie, mit dembash
Sie tun könnenIFS='_' read -a array <<< "${string}"