Wie spalte ich eine Zeichenfolge auf einem Trennzeichen in Bash?
Habe ich diesen string in einer Variablen gespeichert:
IN="[email protected];[email protected]"
Nun würde ich gerne splitten der strings durch ;
Trennzeichen, so dass ich habe:
ADDR1="[email protected]"
ADDR2="[email protected]"
Brauche ich nicht unbedingt die ADDR1
und ADDR2
Variablen. Wenn Sie Elemente in einem array, ist das noch besser.
Nach Anregungen aus den Antworten unten, landete ich mit den folgenden das ist, was ich wurde nach:
#!/usr/bin/env bash
IN="[email protected];[email protected]"
mails=$(echo $IN | tr ";" "\n")
for addr in $mails
do
echo "> [$addr]"
done
Ausgabe:
> [bla@some.com]
> [john@home.com]
Es wurde eine Lösung mit Einstellung Internal_field_separator (IFS);
. Ich bin nicht sicher, was passiert mit ihm, wie setzen Sie IFS
auf Standard zurück?
RE: IFS
Lösung, ich versuchte dies und es funktioniert, ich halte die alten IFS
und dann wieder:
IN="[email protected];[email protected]"
OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
echo "> [$x]"
done
IFS=$OIFS
BTW, als ich versucht
mails2=($IN)
Habe ich nur die erste Zeichenfolge in der Ausgabe in der Schleife, ohne Klammern um $IN
es funktioniert.
InformationsquelleAutor der Frage stefanB | 2009-05-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie die internal field separator (IFS) variable, und lassen Sie ihn dann zu Parsen und in ein array. Wenn dies geschieht in einem Befehl, dann wird die Zuordnung zu
IFS
erfolgt nur zu diesem einzigen Befehl, der die Umgebung (read
). Anschließend analysiert die Eingaben gemäß derIFS
Wert der variable in ein array, und die kann man dann Durchlaufen.Wird es Parsen einer Zeile von Elementen, getrennt durch
;
schob es in ein array. Sachen, die für die Verarbeitung ganz$IN
jedes mal, wenn eine Zeile der Eingabe getrennt durch;
:InformationsquelleAutor der Antwort Johannes Schaub - litb
Entnommen Bash-shell-script, split-array:
Erklärung:
Diese Konstruktion ersetzt alle vorkommen von
';'
(die erste//
bedeutet global replace) in der ZeichenketteIN
mit' '
(ein einzelnes Leerzeichen), dann interpretiert das Leerzeichen als Trennzeichen Zeichenfolge als ein array (das ist das, was die umgebenden Klammern).Die verwendete syntax innerhalb der geschweiften Klammern zu ersetzen, die jeder
';'
Charakter mit einem' '
Charakter heißt Parameter Expansion.Gibt es einige typische Hinweise:
IFS=':'; arrIN=($IN); unset IFS;
IFS=$'\n'; arrIN=($IN); unset IFS;
InformationsquelleAutor der Antwort palindrom
Wenn Sie nichts dagegen haben, verarbeiten Sie diese sofort, ich mag, dies zu tun:
Könnte man diese Art von Schleife, um ein array zu initialisieren, aber es gibt wahrscheinlich einen einfacheren Weg, es zu tun. Hoffe, das hilft, aber.
InformationsquelleAutor der Antwort Chris Lutz
Kompatibel beantworten
Dieser Frage ALSO, es gibt bereits eine Menge von verschiedenen Weg, um dies zu tun, in bash.
Aber bash hat viele Besondere Funktionen, so genannte bashism, die gut funktionieren, aber das funktioniert nicht in jedem anderen Schale.
Insbesondere arraysassoziatives arrayund pattern substitution sind Reine bashisms und funktioniert nicht unter anderen Schalen.
Auf meine Debian GNU/Linuxes ist ein standard shell namens Bindestrichaber ich kenne viele Leute, die wie zu verwenden ksh.
Schließlich in sehr kleine situation, es gibt ein spezielles tool namens busybox mit seiner eigenen shell-interpreter (ash).
Gewünschten Text
Den string-Beispiel in Frage ALSO ist:
Werden, denn dies könnte nützlich sein, mit Leerzeichen und als Leerzeichen ändern könnte, das Ergebnis der routine, ich bevorzuge in diesem Beispiel-string:
Split-string basierend auf Trennzeichen in bash (version >=4.2)
Unter Reine bash, verwenden wir arrays und IFS:
Verwendung dieser syntax unter den letzten bash nicht ändern
$IFS
für die aktuelle Sitzung, sondern nur für den aktuellen Befehl:Nun den string
var
aufgeteilt und gespeichert in ein array (namensfields
):Könnten wir die Anfrage für die Variablen Inhalte mit
declare -p
:read
ist die quickiest Art und Weise zu tun, die Trennung, weil es keine Gabeln und keine externen Ressourcen genannt.Von dort aus können Sie mit der syntax, die Sie bereits wissen, für die Verarbeitung der einzelnen Felder:
oder drop jedes Feld nach der Bearbeitung (ich mag diese Verlagerung Ansatz):
oder auch für den einfachen Ausdruck (kürzere syntax):
Split-string basierend auf Trennzeichen in Schale
Aber wenn Sie etwas schreiben, nutzbar unter vielen Muscheln, die Sie haben, um nicht verwenden bashisms.
Gibt es eine syntax, die in vielen shells, die für die Spaltung einer Schnur über ersten oder letzten vorkommen eines Zeichens:
(Das fehlen dieser ist der Hauptgrund meiner Antwort Publikation 😉
Wie bereits von Score_Under:
Diesem kleinen Beispiel script funktioniert auch unter bashBindestrichkshbusybox und wurde getestet unter Mac-OS-bash:
Spaß haben!
InformationsquelleAutor der Antwort F. Hauri
Wie wäre dieser Ansatz:
Quelle
InformationsquelleAutor der Antwort
Ich habe gesehen, ein paar Antworten verweisen auf die
cut
Befehl, aber Sie haben alle schon gelöscht. Es ist ein wenig seltsam, dass sich niemand erarbeitet hat, weil ich denke, es ist eines der nützlichsten Befehlen für tun, diese Art der Sache, vor allem für die Analyse getrennte log-Dateien.Im Fall der Aufspaltung dieses spezifische Beispiel in ein bash-script array
tr
ist wahrscheinlich effizienter, abercut
verwendet werden kann, und ist effektiver, wenn Sie möchten, ziehen Sie bestimmte Felder von der Mitte.Beispiel:
Können Sie offensichtlich, dass in eine Schleife, und wiederholen den -f-parameter zu ziehen jedes Feld einzeln.
Diese bekommt mehr sinnvoll, wenn Sie eine getrennte log-Datei mit Zeilen wie dieser:
cut
ist sehr praktisch, um in der Lage sein, umcat
diese Datei und wählen Sie einen bestimmten Bereich für die weitere Verarbeitung.InformationsquelleAutor der Antwort DougW
Dieser arbeitete für mich:
InformationsquelleAutor der Antwort Steven Lizarazo
InformationsquelleAutor der Antwort lothar
Funktioniert das auch:
Vorsicht, diese Lösung ist nicht immer richtig. In Fall, dass Sie pass "[email protected]" nur, es ordnet Sie beide ADD1 und ADD2.
InformationsquelleAutor der Antwort Ashok
Ich denke AWK ist die beste und effizienteste Befehl, um Ihr problem zu lösen. AWK ist enthalten in der Bash standardmäßig in fast allen Linux-distribution.
geben
Natürlich können die Speicherung der einzelnen E-Mail-Adresse durch die Neudefinition des awk-print-Feld.
InformationsquelleAutor der Antwort Tony
Anders Die Antwort von Darrondas ist, wie ich es mache:
InformationsquelleAutor der Antwort nickjb
In der Bash, eine Kugel-Beweis Weg, dass funktioniert sogar, wenn die variable enthält Zeilenumbrüche:
Aussehen:
Den trick für diese arbeiten ist die Verwendung der
-d
Möglichkeitread
(delimiter) mit einem empty delimiter, so dassread
ist gezwungen, alles zu Lesen, es ist gefüttert. Und wir fütternread
mit genau der Inhalt der variablein
mit ohne abschließendes newline Dankprintf
. Beachten Sie, dass wir sind auch dabei, das Trennzeichen inprintf
um sicherzustellen, dass die Zeichenfolge übergeben, umread
hat eine nachgestellte Trennzeichen. Ohne Sieread
würde trim Potenzial nachgestellte leere Felder:das leere Feld erhalten.
Update für Bash≥4.4
Da Bash 4.4, die vordefiniert
mapfile
(akareadarray
) unterstützt die-d
option geben Sie ein Trennzeichen. Damit ein anderes kanonische Weg ist:InformationsquelleAutor der Antwort gniourf_gniourf
Wie über diese eine, liner, wenn du nicht mit arrays:
InformationsquelleAutor der Antwort Darron
Ohne Einstellung der IFS -
Wenn Sie nur noch ein Doppelpunkt das können Sie tun:
erhalten Sie:
InformationsquelleAutor der Antwort Emilien Brigand
Hier ist eine saubere 3-liner:
wo
IFS
begrenzen Wörter basierend auf den separator und die()
verwendet wird, um eine array. Dann[@]
zurück, jeden Artikel als separates Wort.Wenn Sie noch irgendwelche code nach, dass, müssen Sie auch wiederherstellen
$IFS
z.B.unset IFS
.InformationsquelleAutor der Antwort kenorb
Gibt es eine einfache und intelligente Art und Weise, wie diese:
Aber Sie müssen gnu-xargs, BSD xargs nicht unterstützen -d delim. Wenn Sie apple mac, wie ich. Sie können installieren, gnu xargs :
dann
InformationsquelleAutor der Antwort Victor Choy
Dies ist der einfachste Weg, es zu tun.
InformationsquelleAutor der Antwort Prospero
Dem folgenden Bash/zsh-Funktion teilt das erste argument auf das Trennzeichen gegeben durch das zweite argument:
Beispielsweise den Befehl
Erträge
Diese Ausgabe kann zum Beispiel an andere Befehle. Beispiel:
Im Vergleich zu den anderen Lösungen gegeben, diese hat die folgenden Vorteile:
IFS
wird nicht überschrieben:, da dynamisches scoping auch lokale Variablen überschreibenIFS
über eine Schleife führt den neuen Wert ein Leck in Funktionsaufrufe durchgeführt, die in der Schleife.Arrays nicht verwendet werden: Lesen Sie einen string in ein array mit
read
erfordert die Flagge-a
in Bash und-A
im zsh.Falls gewünscht, kann die Funktion in einem Skript wie folgt:
InformationsquelleAutor der Antwort Halle Knast
Ausgabe
System : Ubuntu 12.04.1
InformationsquelleAutor der Antwort rashok
können Sie anwenden, awk, um viele Situationen
auch Sie können diese
InformationsquelleAutor der Antwort shuaihanhungry
Wenn kein Platz ist, Warum nicht?
InformationsquelleAutor der Antwort ghost
Gibt es ein paar Coole Antworten hier (errator esp.), aber für etwas Analog zu split in anderen Sprachen-das ist, was ich fand, die ursprüngliche Frage zu meine-ich ließ mich auf dieses:
Nun
${a[0]}
${a[1]}
usw. sind wie man es erwarten würde. Verwenden${#a[*]}
für die Anzahl der Bedingungen. Oder Durchlaufen, natürlich:WICHTIGER HINWEIS:
Dies funktioniert in den Fällen, wo es keine Räume zu sorgen, das mein problem gelöst, aber kann Sie nicht lösen, Ihre. Gehen Sie mit der
$IFS
Lösung(en) in diesem Fall.InformationsquelleAutor der Antwort eukras
Verwenden Sie die
set
built-in zu laden, bis die$@
array:Dann, lasst die party beginnen:
InformationsquelleAutor der Antwort jeberle
Beiden bourne-ish alternativen, wo weder erfordern die bash-arrays:
Fall 1: Halten Sie es schön und einfach: Verwenden Sie ein NewLine als Datensatz-Trennzeichen... zB.
Hinweis: in diesem ersten Fall kein sub-Prozess abgespalten, um mit Hilfe der Liste manipulation.
Idee: Vielleicht lohnt es sich, mit NL ausgiebig internund nur die Konvertierung auf einen anderen RS bei der Generierung des endgültigen Ergebnisses extern.
Fall 2: Mit einem ";" als satztrennzeichen... zB.
In beiden Fällen ist eine sub-Liste verfasst werden kann innerhalb der Schleife ist persistent, nachdem die Schleife abgeschlossen wurde. Dies ist nützlich bei der Manipulation von Listen im Speicher, anstatt das speichern von Listen in Dateien. {p.s. keep calm and carry on-B-) }
InformationsquelleAutor der Antwort NevilleDNZ
Abgesehen von der fantastischen Antworten, wurden bereits zur Verfügung gestellt, wenn es ist nur eine Frage der Ausdruck der Daten können Sie erwägen, mit
awk
:Dieser legt die Trennzeichen für Felder
;
so dass es eine Schleife durch die Felder mit einemfor
Schleife und Druck entsprechend an.Test
Mit einem Eingang:
InformationsquelleAutor der Antwort fedorqui
In der Android-shell, die meisten der vorgeschlagenen Methoden einfach nicht funktionieren:
Was funktioniert ist:
wo
//
bedeutet weltweiten Austausch.InformationsquelleAutor der Antwort 18446744073709551615
Okay Jungs!
Hier ist meine Antwort!
Warum dieser Ansatz ist "das beste" für mich?
Wegen zwei Gründen:
[]'s
InformationsquelleAutor der Antwort Eduardo Lucio
Einen one-liner nach split einen string, getrennt durch ';' in ein array ist:
Diese legt nur wenns in einer subshell, so dass Sie nicht haben, um sorgen über das speichern und die Wiederherstellung seiner Wert.
InformationsquelleAutor der Antwort Michael Hale
Ausgabe:
Erklärung: Einfache Zuweisung mit Klammern () konvertiert Semikolon getrennte Liste in ein array, sofern Sie die richtige IFS dabei. Standard-FOR-Schleife verarbeitet einzelne Elemente im array wie gewohnt.
Beachten Sie, dass die Liste, die für die IN-variable muss "hart" zitiert, das heißt, mit einzelnen ticks.
Wenns sein muss, gespeichert und wiederhergestellt werden, da die Bash nicht die Behandlung einer Zuweisung die gleiche Weise wie ein Befehl. Eine Alternative Problemumgehung ist, um wickeln Sie die Zuordnung innerhalb einer Funktion, und rufen Sie die Funktion mit einem modifizierten IFS. In diesem Fall trennen, speichern/wiederherstellen der IFS ist nicht erforderlich. Vielen Dank für "Bize" für den Hinweis.
InformationsquelleAutor der Antwort ajaaskel
Vielleicht nicht die eleganteste Lösung, funktioniert aber mit
*
Raum:Ausgänge
Anderen Beispiel (Trennzeichen am Anfang und am Ende):
Im Grunde ist es entfernt alle anderen Zeichen als
;
machendelims
zB.;;;
. Dann macht esfor
Schleife aus1
zunumber-of-delimiters
als gezählt${#delims}
. Der Letzte Schritt ist sicher das$i
TEN Teil mitcut
.InformationsquelleAutor der Antwort Petr Újezdský