split()
In JavaScript ist es sehr einfach, einen String in ein Array zu unterteilen.
Was ist mit Shell-Skript?
Angenommen, ich möchte Folgendes tun:
$ script.sh var1_var2_var3
Wenn der Benutzer var1_var2_var3
der script.sh einen solchen String gibt, konvertiert er den String innerhalb des Skripts in ein Array wie
array=( var1 var2 var3 )
for name in ${array[@]}; do
# some code
done
shell
shell-script
string
AGamePlayer
quelle
quelle
shell
Sie, mit dembash
Sie tun könnenIFS='_' read -a array <<< "${string}"
perl
kann das auch. Es ist keine "reine" Hülle, aber es ist ziemlich verbreitet.Antworten:
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[@]}
stattfor 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
) desglob
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
_
:Um die Unterscheidung zwischen Trennzeichen und Trennzeichen zu sehen , probieren Sie Folgendes aus:
Das wird spaltete es in
var1
undvar2
nur (kein zusätzliches leeres Element).Um es ähnlich wie JavaScript zu machen
split()
, benötigen Sie einen zusätzlichen Schritt:(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:
(wo bekommt man
var1
undvar2
) mitwo Sie bekommen:
''
,var1
,''
,var2
,''
.Beachten Sie, dass die
zsh
Shell diesen split + glob-Operator nur implizit aufruft, wenn er insh
oderksh
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:oder um die leeren Elemente zu erhalten:
Beachten Sie, dass es
s
zum Teilen , nicht zum Abgrenzen (auch bei$IFS
einer bekannten POSIX-Abweichung vonzsh
) gibt. Es unterscheidet sich von JavaScriptsplit()
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 dieabc
Zeichenfolge aufteilt , während sich mitIFS=abc
, das aufteilen würdea
,b
oderc
.Mit
zsh
undksh93
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 BeispielIFS=_; set -f; set -- $@
wäre nicht gleichbedeutend mitIFS=_; 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
einensplit
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).Die
zsh
Shell verfügt über eine integrierte Unterstützung für Perl-kompatible reguläre Ausdrücke (in ihremzsh/pcre
Modul). Die Verwendung dieser Funktion zum Teilen einer Zeichenfolge ist jedoch relativ umständlich.quelle
$PATH
auf:
) , im Gegenteil, mögen Sie in der Regel leere Elemente bewahren. Beachten Sie, dass in der Bourne-Shell alle Zeichen die Sonderbehandlung erhieltenksh
und dass nur die leeren Zeichen (nur Leerzeichen, Tabulator und Zeilenvorschub) speziell behandelt wurden.zsh
Behandlung mit einer Zeichenfolge hinzufügen, die 2 oder mehr Zeichen enthält${(s:string:)var}
. Wenn hinzugefügt, kann ich meine Antwort löschen :)S
steht für Separator , nicht für Delimiter . Zumindest steht das in meinem Bash-Handbuch.$IFS
stammt aus der Bourne-Shell, in der es sich um ein Trennzeichen handelte . ksh änderte das Verhalten, ohne den Namen zu ändern. Ich erwähne das, um zu betonen, dasssplit+glob
(außer in zsh oder pdksh) nicht mehr einfach geteilt wird.Ja, benutze
IFS
und setze es auf_
. Verwenden Sie dannread -a
, um in einem Array zu speichern (-r
deaktiviert die Backslash-Erweiterung). Beachten Sie, dass dies spezifisch für bash ist. ksh und zsh haben ähnliche Funktionen mit leicht unterschiedlicher Syntax, und plain sh hat überhaupt keine Array-Variablen.Von
man bash
:Beachten Sie, dass dies
read
bei der ersten Zeile endet. Pass-d ''
auf ,read
um das zu vermeiden, aber in diesem Fall wird es ein extra Newline am Ende aufgrund des<<<
Betreibers. Sie können es manuell entfernen:quelle
$r
Dies setzt voraus, dass keine Zeilenumbrüche oder Backslashes enthalten sind. Beachten Sie auch, dass dies nur in neueren Versionen derbash
Shell funktioniert .bash
,read -a
wurde in Bash 4 eingeführt, oder?<<<
wurde erst kürzlich hinzugefügt,bash
aber es scheint, dass es seit 2.05b (2002) da ist.read -a
ist noch älter als das.<<<
kommt vonzsh
und wird auch vonksh93
(und mksh und yash) unterstützt,read -a
ist aber bash-spezifisch (es ist-A
in ksh93, yash und zsh).