HOWTO · Bash
Teilstring in Bash extrahieren
Dieses Tutorial zeigt verschiedene Möglichkeiten zum Extrahieren einer TeilZeichenkette in bash mit dem Befehl cut, der TeilZeichenkettenerweiterung und dem internen Feldtrennzeichen.
Auf dieser Seite
Um einen Teil einer Zeichenkette in Bash zu erhalten, wählen Sie die Operation passend zur Eingabe: cut wählt ein durch Trennzeichen abgegrenztes Feld aus, die Teilstring-Expansion von Bash wählt Zeichen anhand ihrer Position aus, und durch das Aufteilen mit IFS wird abgegrenzter Text in einzelne Felder zerlegt, die Sie separat verarbeiten können. Die Verfahren sind verwandt, liefern aber unterschiedliche Ergebnisse.
Ein abgegrenztes Feld mit cut auswählen
Verwenden Sie cut, wenn ein Wert ein einheitliches Trennzeichen hat und Sie ein bestimmtes Feld benötigen. Mit der Option -d legen Sie das Trennzeichen fest, mit -f wählen Sie eine Feldnummer aus; die Zählung beginnt bei eins. In diesem Beispiel trennen Unterstriche die Wörter, daher ist Feld 3 gleich three. Setzen Sie die Variablenexpansion in Anführungszeichen und übergeben Sie sie an printf. So bleibt der Wert eine einzelne Eingabezeile, und die unsichere unquotierte Form echo $numbers wird vermieden.
Führen Sie dieses Beispiel aus. Die Bezeichnungen im Code und in der Ausgabe bleiben auf Englisch:
numbers='one_two_three_four_five'
substring=$(printf '%s\n' "$numbers" | cut -d '_' -f 3)
printf 'substring: %s\n' "$substring"
substring: three
cut wählt Felder und keinen beliebigen Zeichenbereich aus. Das Verfahren eignet sich für strukturierten Text, bei dem Trennzeichen und Feldpositionen bekannt sind. Geht es stattdessen um einen Bereich anhand seiner Position, verwenden Sie die Teilstring-Expansion.
Zeichen mit der Teilstring-Expansion von Bash extrahieren
Bash stellt die Teilstring-Expansion in der Form ${variable:offset:length} bereit. Der Offset beginnt bei null; die Länge gibt an, wie viele Zeichen zurückgegeben werden. In one_two_three_four_five beginnt Offset 4 beispielsweise beim t in two, und Länge 3 wählt diese drei Zeichen aus. Alle Zeichen der ursprünglichen Zeichenkette, auch die Trennzeichen, zählen für den Offset mit.
Führen Sie dieses Beispiel aus. Die Bezeichnungen im Code und in der Ausgabe bleiben auf Englisch:
numbers='one_two_three_four_five'
substring=${numbers:4:3}
printf 'substring: %s\n' "$substring"
substring: two
Dieses Verfahren ist die direkte Wahl, wenn Zeichenposition und Bereich bekannt sind. Der Offset ist keine Feldnummer: Ändert sich die Länge des Textes vor dem gewünschten Teil, kann derselbe Offset andere Zeichen auswählen. Bei einem Wert, der in benannte oder nummerierte Felder unterteilt ist, lassen sich cut oder IFS meist leichter anpassen.
Eine Zeichenkette mit IFS in Felder aufteilen
IFS ist der Internal Field Separator von Bash (der interne Feldtrenner). Er steuert die Wortaufteilung nach einer unquotierten Expansion und beeinflusst außerdem, wie das eingebaute Kommando read Eingaben aufteilt. Mit einem vorübergehend gesetzten Wert für IFS lässt sich eine abgegrenzte Zeichenkette in Positionsparameter aufteilen. $1, $2 und $3 bezeichnen den ersten, zweiten und dritten Parameter; sie sind keine Array-Indizes.
Das Beispiel beschränkt die Aufteilung auf eine Funktion und deaktiviert vor der unquotierten Expansion die Pfadnamenerweiterung. Das ist wichtig, weil auf die Wortaufteilung die Pfadnamenerweiterung folgt: Enthält ein Feld *, ? oder ein Muster mit eckigen Klammern, könnte die Shell es sonst durch passende Dateinamen ersetzen. Verwenden Sie diese Form nur für kontrollierte Eingaben mit einem bekannten Trennzeichen. Ist das Trennzeichen kein Leerraum, setzen Sie IFS darauf, lesen Sie die Eingabe mit read -a in ein Array ein und setzen Sie die Array-Expansionen bei der Verwendung der Felder in Anführungszeichen. Standardmäßig teilt IFS Felder an Leerzeichen, Tabulatoren und Zeilenumbrüchen. Wird IFS auf ein Trennzeichen gesetzt, teilt dieses die Eingabe. Felder, die das gewählte Trennzeichen enthalten, bleiben dabei nicht erhalten. Außerdem kann das zeilenorientierte read -a eingebettete Zeilenumbrüche nicht als Bestandteil eines Feldes bewahren. Verwenden Sie für solche Formate einen dafür ausgelegten Parser, statt sich allein auf read -a zu verlassen.
Führen Sie dieses Beispiel aus. Die Bezeichnungen im Code und in der Ausgabe bleiben auf Englisch:
numbers='one_two_three_four_five'
extract_second() (
local IFS=_
set -f
set -- $numbers
printf 'second field: %s\n' "$2"
)
extract_second
second field: two
Innerhalb der Funktion ersetzt set -- ihre Positionsparameter durch die aufgeteilten Felder. Beim Verlassen der Funktion werden die Positionsparameter des Aufrufers wiederhergestellt. Der lokale Feldtrenner ändert den Wert von IFS im Skript nicht dauerhaft.
Die passende Methode auswählen
Wählen Sie cut, um aus Text mit einem bekannten Trennzeichen ein nummeriertes Feld auszuwählen, etwa den dritten durch Unterstriche getrennten Wert. Mit der Teilstring-Expansion von Bash extrahieren Sie Zeichen ab einem bekannten nullbasierten Offset und über eine bekannte Länge. Verwenden Sie das Aufteilen mit IFS, wenn die Felder als separate Shell-Wörter oder Positionsparameter für die weitere Verarbeitung benötigt werden.
Bei vorhersehbaren Eingaben ist jede dieser Möglichkeiten kompakt. Setzen Sie die Eingabe für cut in Anführungszeichen, verwenden Sie geschweifte Klammern für die Teilstring-Expansion und beachten Sie, dass eine unquotierte Expansion beim Aufteilen mit IFS auch die Pfadnamenerweiterung auslösen kann. Ist das Trennzeichen Teil der Daten oder können Feldinhalte Shell-Musterzeichen enthalten, verwenden Sie ein Parsing-Verfahren, das die Felder als quotierte Array-Elemente erhält, statt sich auf eine unquotierte Wortaufteilung zu verlassen. So vermeiden Sie, Feldnummer, Zeichenoffset und Positionsparameter fälschlich als austauschbare Formen eines „Teilstrings“ zu behandeln.