Erweiterung einer Shell-Variablen und Auswirkung von glob und Split darauf

18

Dieser Beitrag enthält eigentlich zwei getrennte Fragen, aber ich denke, dass eine Gruppierung dieser Fragen mehr Kontext ergibt. Ich habe diese Frage zu Anführungszeichen für Variablen durchgearbeitet, verstehe aber nicht ganz, was Variablenerweiterung überhaupt bedeutet. Meine erste Frage lautet also:

  1. Was ist variable Expansion unter Unix / Linux?

Ein zweiter Teil meiner Frage bezieht sich auf folgende Begriffe:

  1. glob
  2. Teilt

Was bedeuten die oben genannten und wie wirken sie sich auf die variable Expansion aus? In der Antwort auf die ursprüngliche Frage wird Folgendes erwähnt:

Stellen Sie sich das Fehlen von Anführungszeichen (in Listenkontexten) als den Operator split + glob vor.

Als ob echo $ test echo glob wäre (split ("$ test")).

Ich konnte keine Antworten finden, die direkt auf das Konzept des Globbing und Splitting eingehen , sondern diese Begriffe direkt für die Beantwortung anderer Fragen wie dieser jüngsten verwenden .

Aussenseiter
quelle

Antworten:

15

Variablenerweiterung (der Standardbegriff ist Parametererweiterung und wird manchmal auch als Variablensubstitution bezeichnet ) bedeutet im Grunde, die Variable durch ihren Wert zu ersetzen. Genauer gesagt bedeutet dies, dass das $VARIABLEKonstrukt (oder ${VARIABLE}oder ${VARIABLE#TEXT}andere Konstrukte) durch einen anderen Text ersetzt wird, der aus dem Wert der Variablen erstellt wird. Dieser andere Text ist die Erweiterung der Variablen.

Der Expansionsprozess läuft wie folgt ab. (Ich diskutiere nur den allgemeinen Fall, einige Shell-Einstellungen und -Erweiterungen ändern das Verhalten.)

  1. Nehmen Sie den Wert der Variablen, die eine Zeichenfolge ist. Wenn die Variable nicht definiert ist, verwenden Sie die leere Zeichenfolge.
  2. Wenn das Konstrukt eine Transformation enthält, wenden Sie diese an. Wenn das Konstrukt beispielsweise ist ${VARIABLE#TEXT}und der Wert der Variablen mit beginnt TEXT, entfernen Sie TEXTvom Anfang des Werts.
  3. Wenn der Kontext ein einzelnes Wort erfordert (z. B. in doppelten Anführungszeichen oder auf der rechten Seite einer Zuweisung oder in einem Here-Dokument), hören Sie hier auf. Fahren Sie andernfalls mit den nächsten Schritten fort.
  4. Teilen Sie den Wert bei jeder Folge von Leerzeichen in separate Wörter auf. (Die Variable IFSkann so geändert werden, dass sie nur mit Leerzeichen geteilt wird.) Das Ergebnis ist also keine Zeichenfolge mehr, sondern eine Liste von Zeichenfolgen. Diese Liste kann leer sein, wenn der Wert nur Leerzeichen enthält.
  5. Behandeln Sie jedes Element der Liste als Platzhalter für Dateinamen, dh als Glob . Wenn das Muster mit einigen Dateien übereinstimmt, wird es durch die Liste der übereinstimmenden Dateinamen ersetzt, andernfalls wird es in Ruhe gelassen.

Angenommen, dass der Variable fooenthält a* b* c*und das aktuelle Verzeichnis enthält die Dateien bar, bazund paz. Dann ${foo#??}wird wie folgt erweitert:

  1. Der Wert der Variablen ist die 8-stellige Zeichenfolge a* b* c*.
  2. #??bedeutet, dass die ersten beiden Zeichen entfernt werden, was zu einer 6-stelligen Zeichenfolge  b* c*(mit einem anfänglichen Leerzeichen) führt.
  3. Befindet sich die Erweiterung in einem Listenkontext (dh nicht in doppelten Anführungszeichen oder einem ähnlichen Kontext), fahren Sie fort.
  4. Teilen Sie die Zeichenfolge in durch Leerzeichen getrennte Wörter auf, sodass eine Liste mit zwei Zeichenfolgen angezeigt wird: b*und c*.
  5. Die b*als Muster interpretierte Zeichenfolge entspricht zwei Dateien: barund baz. Die Zeichenfolge c*stimmt mit keiner Datei überein, sodass sie in Ruhe gelassen wird. Das Ergebnis ist eine Liste von drei Strings: bar, baz, c*.

Zum Beispiel echo ${foo#??}Ausdrucke bar baz c*(der Befehl echoverbindet seine Argumente mit einem Leerzeichen dazwischen).

Weitere Einzelheiten finden Sie unter:

Gilles 'SO - hör auf böse zu sein'
quelle
2
Man beachte , dass es heißt Parameter Expansion , weil es auf Variablen (gilt $var) und andere Arten von Parametern wie $1, $#, $?, $-...
Stéphane Chazelas
12

glob / split

Ich nehme zuerst den Glob / Split. @ Stephanes Antwort , mit der Sie verlinkt sind, ist die Verwendung dieser Begriffe im Allgemeinen. Sie sind keine tatsächlichen Befehle oder ähnliches, sondern nur Pseudooperationen.

Das split("$test")würde den Inhalt von "$ test" in ein "Array" von Elementen aufteilen.

Das glob(...)würde dann darauf achten, eines dieser Elemente zu erweitern, die Shell-Globbing-Zeichen wie *oder Bereiche enthalten [1-2].

Beispiel

Angenommen, unsere Zeichenfolge $testlautet wie folgt.

$ test="afile[1-2] afile[3-5]"

Nehmen wir auch an, wir haben ein Verzeichnis mit einigen Dateien.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Wenn wir nun versuchen, es ohne Anführungszeichen wiederzugeben, sollten Sie feststellen, dass unsere Zeichenfolge in Leerzeichen aufgeteilt wurde und dann alle glühenden Zeichen erweitert wurden.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Wenn wir die Variable jedoch als Argument für die echoÜbergabe in Anführungszeichen setzen, erhalten wir die ursprüngliche Literalzeichenfolge.

$ echo "$test"
afile[1-2] afile[3-5]

variable Ausdehnung

Der Begriff Variablenerweiterung soll die Grundoperation abdecken, die die Shell als Teil ihrer Grundoperationen ausführt. Die Shell ist für das Parsen der Eingabe verantwortlich und führt diese Eingabe aus, sobald sie als syntaktisch korrekt erachtet wird.

In unserem vorherigen Beispiel. Als die Variable nicht $testin echoAnführungszeichen gesetzt wurde, forderten wir die Shell auf, diese Argumente aufzuteilen und sie dann zu globalisieren.

Als es in Anführungszeichen gesetzt wurde, deaktivierten wir dieses Feature im Wesentlichen mit den Variablen, die wir in doppelte Anführungszeichen eingeschlossen hatten.

Beispiel

Hier sind einige zusätzliche Beispiele für Globbing und Splitting.

Glob / Splitting erfolgt automatisch

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

Glob / Splitting über doppelte Anführungszeichen deaktiviert

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
slm
quelle
Ich wusste nicht, dass Bereiche auch in umgekehrter Reihenfolge funktionieren.
Joe