Ich habe eine Zeichenfolge:
one_two_three_four_five
Ich muss in einem variablen A
Wert two
und im variablen B
Wert four
von der oben genannten Zeichenkette speichern
Verwenden Sie cut
mit _
als Feldtrennzeichen und erhalten gewünschten Felder:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
Sie können echo
anstelle des Here-Strings auch and pipe verwenden:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
Beispiel:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
Wissen Sie, was hier passiert?echo "${s##*_}"
Mit nur POSIX sh Konstrukten, können Sie Parameter Substitution baut einen Begrenzer zu einem Zeitpunkt , zu analysieren. Beachten Sie, dass dieser Code davon ausgeht, dass die erforderliche Anzahl von Feldern vorhanden ist, andernfalls wird das letzte Feld wiederholt.
Alternativ können Sie eine nicht in Anführungszeichen gesetzte Parametersubstitution mit deaktivierter Platzhaltererweiterung verwenden und
IFS
das Trennzeichen verwenden (dies funktioniert nur, wenn das Trennzeichen ein einzelnes Zeichen ohne Leerzeichen ist oder wenn eine Leerzeichenfolge ein Trennzeichen ist).Dadurch werden die Positionsparameter überlastet. Wenn Sie dies in einer Funktion tun, sind nur die Positionsparameter der Funktion betroffen.
Ein weiterer Ansatz ist die Verwendung des
read
eingebauten.quelle
unset IFS
kehrt nichtIFS
zum Standard zurück. Wenn danach jemandOldIFS="$IFS"
einen Nullwert in OldIFS hat. Außerdem wird davon ausgegangen, dass der vorherige Wert von IFS der Standardwert ist, was durchaus möglich (und sinnvoll) ist, nicht zu sein. Die einzig richtige Lösung ist das Speichernold="$IFS"
und spätere Wiederherstellen mit IFS = "$ old". Oder ... eine Unterschale verwenden(...)
. Oder besser noch, lies meine Antwort.unset IFS
wird nichtIFS
auf den Standardwert zurückgesetzt, aber die Feldaufteilung wird auf den Standardeffekt zurückgesetzt. Ja, dies ist eine Einschränkung, in der Praxis jedoch in der Regel akzeptabel. Das Problem mit einer Subshell ist, dass wir Daten daraus holen müssen. Ich zeige eine Lösung, die den Zustand am Ende nicht ändert, mitread
. (Es funktioniert in POSIX-Shells, aber IIRC nicht in der Bourne-Shell, da esread
aufgrund des Here-Dokuments in einer Subshell ausgeführt werden würde .) Die Verwendung von<<<
as in you answer ist eine Variante, die nur in ksh / bash / zsh funktioniert.user/my_folder/[this_is_my_file]*
? Was ich erhalte, wenn ich diesen Schritten folge, ist[this_is_my_file]*
/
.Wollte eine
awk
Antwort sehen, also hier ist eine:quelle
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
Der einfachste Weg (für Shells mit <<<) ist:
Verwenden einer temporalen Variablen,
$a
anstatt sich über$_
eine Shell zu beschweren.In einem vollständigen Skript:
Keine Änderung des IFS, keine Probleme mit
set -f
(Pfadnamenerweiterung) Keine Änderung der Positionsparameter ("$ @").Für eine Lösung, die auf alle Shells portierbar ist (ja, alle POSIX-Versionen enthalten), ohne IFS zu ändern, oder
set -f
verwenden Sie das (etwas komplexere) heredoc-Äquivalent:Verstehen Sie, dass diese Lösung (sowohl das Here-Doc als auch die Verwendung von
<<<
werden alle nachgestellten Zeilenumbrüche entfernen.Und dass dies auf einen " einzeiligen " variablen Inhalt ausgelegt ist.
Lösungen für Mehrzeilige sind möglich, erfordern jedoch komplexere Konstrukte.
Eine sehr einfache Lösung ist in der Bash-Version 4.4 möglich
Es gibt keine Entsprechung für POSIX-Shells, da viele POSIX-Shells keine Arrays haben.
Für Shells mit Arrays gilt möglicherweise
Folgendes : (getestetes Arbeiten in attsh, lksh, mksh, ksh und bash)
Aber mit einer Menge zusätzlicher Klempnerarbeiten zum Speichern und Zurücksetzen von Variablen und Optionen:
In zsh beginnen Arrays mit 1 und teilen die Zeichenfolge nicht standardmäßig.
Es müssen also einige Änderungen vorgenommen werden, damit dies in zsh funktioniert.
quelle
read
werden , sind einfach, solange OP nicht das 76. und 127. Element aus einer langen Zeichenfolge extrahieren möchte ...readarray
könnte für diese Situation einfacher zu verwenden sein.Mit
zsh
könnten Sie den String (on_
) in ein Array aufteilen :und dann auf jedes Element über den Array-Index zugreifen:
Beachten Sie, dass in
zsh
(im Gegensatz zuksh
/bash
) Array-Indizes bei 1 beginnen .quelle
set -f
, der ersten Lösung eine Warnung hinzuzufügen . ...*
vielleicht Sternchen ?set -f
? Ich benutzeread
/ nichtIFS
. Versuchen Sie meine Lösungen mit einer Zeichenfolge wie*_*_*
oder was auch immer ...Ist eine Python-Lösung erlaubt?
quelle
Ein anderes awk Beispiel; einfacher zu verstehen.
Kann auch mit Variablen verwendet werden.
Nehmen wir an:
this_str = "one_two_three_four_five"
Dann funktioniert folgendes:
A = `echo $ {this_str} | awk -F_ '{print $ 1}' `
B =` echo $ {this_str} | awk -F_ '{print $ 2}' `
C =` echo $ {this_str} | awk -F_ '{print $ 3}' `
... und so weiter ...
quelle