String in array in bash aufteilen

8

Ich suche nach einer Möglichkeit, eine Zeichenfolge in bash über eine Trennzeichenfolge aufzuteilen und die Teile in ein Array zu platzieren.

Einfacher Fall:

%Vor%

Gibt Ausgabe

%Vor%

Komplexerer Fall:

%Vor%

Gibt die Ausgabe aus:

%Vor%

Ich möchte, dass die zweite Ausgabe wie

aussieht %Vor%

i.e. Teilen Sie die Zeichenfolge in einer Zeichenfolge statt einer Zeichenfolge. Wie kann ich das tun?

Ich suche nach einer Antwort, die nur diese Zeile im zweiten Skript ändern würde:

%Vor%     
user000001 31.01.2013, 16:49
quelle

5 Antworten

17

IFS Disambiguierung

IFS mean Eingabefeldtrennzeichen , wie list of characters that could be used as separators .

Standardmäßig ist dies auf \t\n eingestellt, was bedeutet, dass eine beliebige Anzahl (größer als Null) von Leerzeichen , Tabellierung und / oder newline könnte eins separator sein.

Also die Zeichenfolge:

%Vor%

Führende und nachfolgende Trennzeichen würden ignoriert und diese Zeichenfolge würde nur 3 enthalten Teile: blah , foo=bar und baz .

Das Aufteilen einer Zeichenfolge mit IFS ist möglich, wenn Sie ein gültiges Feldtrennzeichen kennen, das in Ihrer Zeichenfolge nicht verwendet wird.

%Vor%

Aber das funktioniert nur, solange string nicht § enthält.

Du könntest einen anderen Charakter benutzen, wie IFS=$'6';c_split=(${c//=======/$'6'}) , aber das könnte weitere Fehler beinhalten.

Sie können nach Zeichenkarten suchen, um einen zu finden, der nicht in Ihrer Zeichenkette enthalten ist:

%Vor%

aber ich finde diese Lösung etwas übertrieben.

Teilen auf Leerzeichen (oder ohne IFS zu ändern)

Unter könnten wir diesen Bashismus verwenden:

%Vor%

Tatsächlich wird diese Syntax ${varname// eine Übersetzung initiieren (begrenzt durch / ) und alle Vorkommen von / durch ein Leerzeichen ersetzen, vor Zuweisung zu einem Array b_split .

Natürlich benutzen wir immer noch IFS und teilen Arrays auf Leerzeichen.

Dies ist nicht der beste Weg, aber könnte mit bestimmten Fällen arbeiten.

Sie können sogar unerwünschte Leerzeichen vor dem Teilen löschen:

%Vor%

oder tausche sie aus ...

%Vor%

Teilungslinie auf strings :

Sie müssen also nicht IFS für Ihre Bedeutung verwenden, aber haben schöne Eigenschaften:

%Vor%

Sehen Sie:

%Vor%

Hinweis: Zeilenumbrüche und Zeilenumbrüche werden nicht gelöscht. Wenn dies erforderlich ist, könnten Sie:

%Vor%

statt einfach ======= .

Oder Sie könnten die geteilte Schleife neu schreiben, um dies explizit zu vermeiden:

%Vor%

Auf jeden Fall passt das, wonach SO gefragt ist (: und sein Beispiel:)

%Vor%

Erstellen Sie schließlich ein array

%Vor%

Mach das fein:

%Vor%

Einige Erklärungen:

  • export -a var , um var als Array zu definieren und sie in childs
  • zu teilen
  • ${variablename%string*} , ${variablename%%string*} Ergebnis im linken Teil von Variablenname , bis, aber ohne Zeichenfolge . Ein % bedeutet letztes Auftreten von String und %% für alle Vorkommen . Vollständiger Variablenname wird zurückgegeben, wenn Zeichenfolge nicht gefunden wird.
  • ${variablename#*string} , mache dasselbe in umgekehrter Reihenfolge: gib den letzten Teil von Variablenname aus, aber ohne String . Ein # bedeutet erstes Vorkommen und zwei ## man alle Vorkommen .

Nota ersetzt, Zeichen * ist ein Joker bedeutet eine beliebige Anzahl von beliebigen Zeichen.

Der Befehl echo "${c%%$'\n'}" würde die Variable c ohne eine beliebige Anzahl Zeilenumbrüche am Ende der Zeichenfolge ausgeben.

Wenn Variable Hello WorldZorGluBHello youZorGluBI'm happy enthält,

%Vor%

All dies wird in der Hilfeseite erklärt:

%Vor%

Schritt für Schritt, die Teilungsschleife:

Das Trennzeichen:

%Vor%

Deklaration von c_split als -Array (und könnte mit childs geteilt werden)

%Vor%

Die Variable c enthält mindestens ein Vorkommen von mySep

%Vor%

Trunc c vom ersten mySep bis zum Ende des Strings und Zuweisung an part .

%Vor%

Entfernen Sie führende Zeilenumbrüche

%Vor%

Entfernen Sie abschließende Zeilenumbrüche und fügen Sie das Ergebnis als neues Array-Element zu c_split hinzu.

%Vor%

Erneut c mit dem Rest der Zeichenfolge, wenn bis zu mySep übrig ist, wird entfernt

%Vor%

Fertig; -)

%Vor%

Entfernen Sie führende Zeilenumbrüche

%Vor%

Entfernen Sie abschließende Zeilenumbrüche und fügen Sie das Ergebnis als neues Array-Element zu c_split hinzu.

%Vor%

In eine Funktion:

%Vor%

Verwendung:

%Vor%

Dabei ist Array-Name standardmäßig $splitted_array und Delimiter ist ein einzelnes Leerzeichen.

Sie könnten verwenden:

%Vor%     
F. Hauri 09.02.2013, 15:18
quelle
3

mach es mit awk:

%Vor%

Ausgabe:

%Vor%     
Kent 31.01.2013 17:01
quelle
1

Folgendes Skript wurde in bash getestet:

%Vor%

das Skript: (named t.sh )

%Vor%

Ausgabe:

%Vor%

Notiz die Echo-Anweisung in dieser for-Schleife, wenn Sie die Option -e entfernen, sehen Sie:

%Vor%

nehmen -e oder nicht hängt von Ihrer Anforderung ab.

    
Kent 04.02.2013 10:20
quelle
1

Hier ist ein Ansatz, der nicht fummelt, wenn die Daten literale Backslash-Sequenzen, Leerzeichen und andere enthalten:

%Vor%

Beachten Sie, dass die Zeichenfolge tatsächlich wie gewünscht auf "=======" aufgeteilt wird, sodass die Zeilenvorschübe Teil der Daten werden (wodurch zusätzliche Leerzeilen entstehen, wenn "echo" eine eigene Zeile hinzufügt).

    
that other guy 06.02.2013 00:05
quelle
1

Einige im Beispieltext wegen dieses Kommentars hinzugefügt:

  

Dies bricht, wenn Sie AA = A durch AA = A oder AA = \ nA - das ersetzen   anderer Typ

BEARBEITEN: Ich habe einen Vorschlag hinzugefügt, der für einige Trennzeichen im Text nicht empfindlich ist. Allerdings verwendet dies nicht eine "Ein-Zeilen-Aufteilung", nach der OP gefragt hat, aber so hätte ich es tun sollen wenn ich es in bash machen würde und das Ergebnis in einem Array haben möchte.

script.sh (NEU):

%Vor%

script.sh (OLD, mit "one line split"):
(Ich hocke die Idee mit awk von @Kent und stelle sie etwas ein)

%Vor%

Ausgabe:

%Vor%

Ich bin nicht und verwende -e für echo , um AA=\nA zu erhalten, um keine neue Zeile zu erstellen

    
244an 06.02.2013 18:31
quelle

Tags und Links