Wie kann die Funktionsdefinition Teil der Pipe-Sequenz in der POSIX-Shell-Grammatik sein?

461
user322908

Die POSIX-Shell-Grammatik unter http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10_02

sagt

pipe_sequence : command | pipe_sequence '|' linebreak command ; command : simple_command | compound_command | compound_command redirect_list | function_definition 

Das heißt, Funktionsdefinition kann ein Begriff in einer Pipe-Sequenz sein. Wie ist das möglich? Die Funktionsdefinition kann keine Standardeingabe oder -ausgabe haben, und es ist kein Befehl, der ausgeführt werden kann. Nur eine Funktion Aufruf, der ein einfacher Befehl kann ausgeführt werden.

Nach dem ersten Kommentar und der Antwort hinzugefügt:

Wenn wir uns function_definitionvon commandhier trennen und es als weitere Alternative hinzufügen, wo immer es commanderscheint, dann machen wir die Grammatik etwas komplizierter.

Aber die Auszahlung ist viel wichtiger: Die Implementierung einer solchen Shell ist viel einfacher.

Denn wenn Sie Funktionsdefinitionen in einer Pipe zulassen, müssen Sie sich mit Fragen befassen, wie z. B. der Umfang der Funktion und in welcher Umgebung sie ausgeführt wird. Ich glaube nicht, dass solche Fragen überhaupt im Standard beantwortet werden.

Was ist schlimmer: etwas mehr Komplexität in der Grammatik oder viel mehr Arbeit und Komplexität für den Implementierer. Wenn ersteres, dann handelt es sich nicht um "Schwanzwedeln mit dem Hund"?

0
Es scheint in Bash zu funktionieren, obwohl es nichts bewirkt: `ls | f () `. choroba vor 7 Jahren 1

2 Antworten auf die Frage

4
Daniel B

Warum wäre das nicht möglich? Ist es sinnlos? Bestimmt. Aber es funktioniert:

$ function asdf { echo "bla"; } | hexdump -C; echo EOF EOF 

Ähnlich:

$ function asdf { echo "bla"; } | asdf | hexdump -C; echo EOF -bash: asdf: command not found EOF 

Das Definieren einer Funktion ist wie jeder andere ein Befehl. Es hat keine Ausgabe und nimmt jedoch keine Eingabe auf. Sie können sogar eine variable Zuordnung vornehmen. Natürlich wieder sinnlos, aber kein Fehler.

Das "Warum" ist wahrscheinlich: KISS. Sie möchten Ihre Grammatik nicht mit unnötiger Komplexität verschmutzen.

Update : Bei näherer Betrachtung habe ich herausgefunden, dass Bash die Pipe-Befehle nach einer Funktionsdefinition nicht einmal ausführt.

Ich glaube, ich habe mich in der ursprünglichen Frage nicht vollständig erklärt. Ich habe die Frage bearbeitet, um sie auf den Punkt zu bringen. Ihre Antwort ist aufschlussreich, danke, aber schauen Sie sich bitte meine Bearbeitung an. user322908 vor 7 Jahren 0
Sie sagen, die Implementierung ist viel einfacher, aber ist das so? Durch weniger Spezialfälle benötigen Sie weniger Code. Weniger Code bedeutet weniger Kopfschmerzen und auch weniger Fehler. Funktionen in Bash haben auch keinen Gültigkeitsbereich. Es ist nicht objektorientiert. Es gibt nur die Umwelt. Zu dem Zeitpunkt ist natürlich eine Funktion ausgeführt. Daniel B vor 7 Jahren 0
1
Stephen Harris

Es ist tatsächlich einfacher für den Implementierer, sich keine Gedanken darüber machen zu müssen. Beim Ausführen einer Pipe wird jede Komponente in einer eigenen Subshell ausgeführt (außer vielleicht der ersten in bash oder der letzten in ksh88 / ksh93, wenn der Befehl nativ ist). Somit würde die Funktionsdefinition in der Mitte einer Pipeline für die Shell-Instanz für diese Komponente der Pipe definiert, außerhalb jedoch nicht sichtbar sein. Dies ist alles automatisch, basierend auf der Semantik von Pipelines.

Wenn Sie Funktionsdefinitionen (oder Aliasdefinitionen oder dumme Befehle wie cd...) in einer Pipeline verhindern möchten, haben Sie die Implementierung kompliziert :-)

Pipe-Befehle werden nicht in Subshells ausgeführt, zumindest in Bash. Sie sind direkte Kindprozesse der Shell. Daniel B vor 7 Jahren 0
Bash Gabeln; Der untergeordnete Prozess ist eine weitere Instanz dieser Bash-Shell. In dieser Shell gesetzte Variablen und andere Änderungen (Funktionen, Verzeichnisänderungen usw.) werden nicht an das übergeordnete Element weitergegeben. Im Sinne dieser Frage kann das so behandelt werden, als wäre es eine Subshell. FWIW die Manpage sagt: Jeder Befehl in einer Pipeline wird als separater Prozess ausgeführt (dh in einer Subshell). `:-) Stephen Harris vor 7 Jahren 1
Nur Bash Builtins (wie Funktionsdefinitionen) werden in einer Subshell ausgeführt (na ja, vielleicht). Alles andere ist bereits ein separater Prozess. Daniel B vor 7 Jahren 0
@DanielB Meine Frage bezog sich wirklich auf den POSIX-Standard ... wo kommentiert er den Standard, ob ein Begriff der Pipeline in einem separaten Prozess, Subshell oder was auch immer ausgeführt wird? user322908 vor 7 Jahren 0
@ user322908 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01 Daniel B vor 7 Jahren 0
@DanielB Es tut mir leid, dass es mir so weh tut ... aber ich sehe immer noch nicht, ob Begriffe in der Pipeline in einem separaten Prozess / Subshell ausgeführt werden, in dem Link, den Sie gepostet haben. user322908 vor 7 Jahren 0
Abschnitt 2.12 "Außerdem befindet sich jeder Befehl einer Pipeline mit mehreren Befehlen in einer Subshell-Umgebung." Stephen Harris vor 7 Jahren 1