Was ist Wortteilung? Warum ist es bei der Shell-Programmierung wichtig?


16

Ich bin verwirrt über die Rolle, die die Wortspaltung spielt zsh. Ich war bei der Programmierung in C, Python oder MATLAB nicht mit diesem Konzept vertraut, und dies hat mein Interesse geweckt, warum die Wortteilung etwas Besonderes für die Shell-Programmierung zu sein scheint.

Ich habe auf dieser und anderen Websites bereits von Worttrennung gelesen, aber keine klare Erklärung für das Konzept gefunden. Wikipedia hat eine Definition der Wortteilung, aber es scheint keine Hinweise darauf zu geben, wie sie auf Unix-Shells angewendet wird.

Hier ist ein Beispiel für meine Verwirrung in zsh:

In den Z Shell FAQ habe ich Folgendes gelesen:

3.1: Warum macht $varwo var="foo bar"nicht was ich erwarte?

In den meisten Bourne-Shell-Derivaten werden Variablen mit mehreren Wörtern, z. B. var="foo bar" in Wörter aufgeteilt, wenn sie an einen Befehl übergeben oder in einer for foo in $varSchleife verwendet werden. Standardmäßig weist zsh dieses Verhalten nicht auf: Die Variable bleibt intakt. (Dies ist kein Fehler! Siehe unten.) Die Option ist SH_WORD_SPLITvorhanden, um Kompatibilität bereitzustellen.

Im Z-Shell-Handbuch habe ich jedoch Folgendes gelesen:

SH_WORD_SPLIT (-y) <K> <S>

Bewirkt, dass die Feldaufteilung bei nicht zitierten Parametererweiterungen durchgeführt wird. Beachten Sie, dass diese Option nichts mit der Wortteilung zu tun hat . (Siehe Parametererweiterung.)

Warum heißt es, dass SH_WORD_SPLITdas nichts mit Wortspaltung zu tun hat ? Spaltet sich nicht genau das, worum es geht?

Antworten:


21

Frühe Shells hatten nur einen einzigen Datentyp: Strings. Es ist jedoch üblich, Listen von Zeichenfolgen zu manipulieren, normalerweise, wenn mehrere Dateinamen als Argumente an ein Programm übergeben werden. Ein weiterer häufiger Anwendungsfall für die Aufteilung ist, wenn ein Befehl eine Liste von Ergebnissen ausgibt: Die Ausgabe des Befehls ist eine Zeichenfolge, die gewünschten Daten sind jedoch eine Liste von Zeichenfolgen. Um eine Liste von Dateinamen in einer Variablen zu speichern, müssen Sie Leerzeichen dazwischen setzen. Dann ein Shell-Skript wie dieses

files="foo bar qux"
myprogram $files

wird myprogrammit drei Argumenten aufgerufen , während die Shell die Zeichenfolge $filesin Wörter aufteilt. Zu dieser Zeit waren Leerzeichen in Dateinamen entweder verboten oder galten allgemein als "Nicht erledigt".

Mit der Korn-Shell wurden Arrays eingeführt: Sie können eine Liste von Zeichenfolgen in einer Variablen speichern. Die Korn-Shell blieb mit der damals etablierten Bourne-Shell kompatibel, so dass bei bloßen Variablenerweiterungen die Wortteilung fortgesetzt wurde und die Verwendung von Arrays einen gewissen syntaktischen Aufwand erforderte. Sie würden das Snippet oben schreiben

files=(foo bar qux)
myprogram "${files[@]}"

Zsh hatte von Anfang an Arrays und sein Autor entschied sich auf Kosten der Abwärtskompatibilität für ein vernünftigeres Sprachdesign. In zsh (unter den Standarderweiterungsregeln) wird $vardie Wortteilung nicht ausgeführt. Wenn Sie eine Liste von Wörtern in einer Variablen speichern möchten, sollten Sie ein Array verwenden. und wenn Sie wirklich Wortspaltung wollen, können Sie schreiben $=var.

files=(foo bar qux)
myprogram $files

Heutzutage müssen Sie mit Leerzeichen in Dateinamen fertig werden, weil viele Benutzer erwarten, dass sie funktionieren, und weil viele Skripts in sicherheitsrelevanten Kontexten ausgeführt werden, in denen ein Angreifer möglicherweise die Kontrolle über Dateinamen hat. Daher ist die automatische Wortteilung oft ein Ärgernis. Daher mein genereller Rat, immer doppelte Anführungszeichen zu verwenden, dh zu schreiben "$foo", es sei denn, Sie verstehen, warum Sie in einem bestimmten Anwendungsfall eine Wortteilung benötigen. (Beachten Sie, dass auch leere Variablenerweiterungen globen.)


Danke Gilles, das ist wirklich hilfreich! Ist es richtig zu sagen, dass grob gesagt die Wortteilung Zeichenfolgen des Formulars "word1 word2 word3"in Listen / Arrays des Formulars umwandelt "word1" "word2" "word3"? Ich habe auch das OP mit einer bestimmten Quelle der Verwirrung in zsh aktualisiert.
Amelio Vazquez-Reina

1
@intrpc "Wortteilung" ist keine Aufteilung nach Wörtern in natürlicher Sprache, sondern nach $IFSZeichen. Daher ist "Feldaufteilung" ein besserer Name. In der Muschelliteratur wird dieses Konzept jedoch häufig als "Wortspaltung" bezeichnet. In der zsh-Dokumentation wird über Wörter gestritten.
Gilles 'SO- hör auf böse zu sein'

1
Siehe auch rc(die plan9-Shell, ebenfalls auf Unix portiert) für ein noch besseres Design als zsh, wenn es um Variablen und Arrays geht.
Stéphane Chazelas

3

Die Wortteilung ist nicht wirklich Shell-spezifisch.

Die meisten Programme, die Texteingaben analysieren müssen, verwenden als ersten Schritt eine Form der Wortteilung. Dies erfolgt vor der Identifizierung anhand dieser "Wörter", Zahlen, Operatoren, Zeichenfolgen, Token und ähnlicher Entitäten, die sie verarbeiten müssen.

Das Besondere an den Shells ist, dass sie die Argumentliste der aufgerufenen Befehle (C argc / argv, python sys.argv) ordnungsgemäß erstellen müssen, einschließlich der Übergabe von Argumenten mit eingebetteten Leerzeichen, leeren Argumenten, benutzerdefinierten Begrenzern usw. Viele Shells verwenden die IFS-Variable, um dort eine gewisse Flexibilität zu ermöglichen.


3

In diesem speziellen Fall der ZSH wird das Wort Aufspalten etwas anders als Feldaufspaltung definiert.

Betrachten wir prog a b c, wird es ganz gleich in drei Argumente übergeben , wie Sie festgelegt IFS. Dies ist Wort Spaltung.

Wenn Sie das tun A="a b c"; prog $A, wird es in drei Argumente übergeben , wenn IFSsonst Raum oder ein Argument enthält. Dies ist Feldaufspaltung.

Definitionen hier sind subtil. Was das Zsh Dokument versucht zu sagen ist , dass, selbst wenn Sie diese Option deaktivieren, prog a b cwird nach wie vor getrennte Argumente bekommen (das ist , was die Leute immer erwarten).


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.