Ist es POSIX-kompatibel, eine Shell-Funktion in einer Pipeline zu verwenden?

460
Tim Bird

Kann eine Shell-Funktion in einer Pipeline verwendet werden?

Angenommen, ich hatte eine Funktion, die wie benannt grep, genannt wurde mygrep. Gibt es eine Möglichkeit, nur POSIX-Shell-Funktionen zu verwenden, um mygrepwie folgt aufrufen zu können :

if ps | mygrep foo ; then echo "process foo is running" fi 

Oder ist das Piping nur auf externe Befehle beschränkt?

1
Was hält dich davon ab zu versuchen? Kamil Maciorowski vor 5 Jahren 1
@ KamilMaciorowski: Vielleicht die Ungewissheit, ob es funktioniert, weil es ein Standard-POSIX-Feature ist, oder ob es funktioniert, weil es eine der Millionen Erweiterungen von ksh / bash / zsh ist. Wenn das OP "nur verwenden ..." erwähnt, ist es am besten anzunehmen, "soll es * funktionieren"? grawity vor 5 Jahren 1
@ grawity Eine vernünftige Vermutung, ich verstehe deinen Punkt. Wenn dies der Fall ist, wäre es ein guter Forschungsaufwand, eigene Ergebnisse in wenigen Schalen zu liefern. Kamil Maciorowski vor 5 Jahren 0
@ grawity Meine Antwort befasst sich jetzt mit diesem Problem. Vielen Dank. Kamil Maciorowski vor 5 Jahren 0

2 Antworten auf die Frage

4
Kamil Maciorowski

Ja. Siehe dieses Dokument .

1. Einleitung

Der Shell- und Dienstprogrammdatenträger von POSIX.1-2017 beschreibt die Befehle und Dienstprogramme, die Anwendungsprogramme von POSIX-konformen Systemen angeboten werden.

Ab 2.9.2 Pipelines :

Eine Pipeline ist eine Folge von einem oder mehreren Befehlen, die durch den Steueroperator '|' getrennt werden.

Ab 2.9.5 Funktionsdefinitionsbefehl :

Eine Funktion ist ein benutzerdefinierter Name, der als einfacher Befehl verwendet wird. [...]

Das Format eines Funktionsdefinitionsbefehls lautet wie folgt:

fname ( ) compound-command [io-redirect ...] 

Ab 2.9 Shell-Befehle :

Ein Befehl ist einer der folgenden:

  • Einfacher Befehl [...]
  • [...]

Trennt also |die Befehle. Ein Befehl kann ein einfacher Befehl sein. Funktionsname wird als einfacher Befehl verwendet. Die Antwort auf Ihre Frage lautet: Ja, diese Syntax

some_command | some_function 

wird von POSIX definiert.


Es ist ziemlich einfach auszuprobieren (getestet mit shvon dashDebian 9):

mygrep() { grep "$@"; }  if ps | mygrep foo ; then echo "process foo is running" fi  if ps | mygrep ps ; then echo "process ps is running" fi 

( ps | mygrep foowird auch einen Prozess erkennen foobar, falls vorhanden. Ich verstehe, dass dieses Problem außerhalb des Umfangs Ihrer Frage liegt und wir können es ignorieren.)

In diesem Beispiel mygrepist das trivial. Es gibt den Exit-Status des letzten (und einzigen) Befehls zurück. Beim Erstellen returnvon Funktionen mit komplexerer Logik benötigen Sie möglicherweise ein spezielles Feature, um den gewünschten Beendigungsstatus zurückzugeben.

Beachten Sie auch, dass die Ausgabe von grepnicht unterdrückt wird. In Pipes kann nicht nur eine Shell-Funktion verwendet werden, auch die Ausgabe kann umgeleitet werden. Beispiel:

if ps | mygrep ps >/dev/null ; then echo "process ps is running" fi 
durch untenstehenden Kommentar ersetzt. SE benahm sich komisch und es sah so aus, als würde mein Kommentar nicht gerettet werden. Tim Bird vor 5 Jahren 0
Es ist mir peinlich, dass ich das selbst nicht probiert habe. Ich dachte, dass der Umgang mit dem stdin etwas komplizierter sein würde, aber im Nachhinein scheint es offensichtlich, dass es nur auf die Funktion "geht" (wenn man es so formuliert). Dass Sie die Funktionsausgabe umleiten können, ist auch sehr interessant. Vielen Dank! Tim Bird vor 5 Jahren 0
-2
Yurij

Sie müssen ein Online-Formular verwenden oder Ihren Ausdruck in $ {} packen. In dieser Form, die Sie als Bash-Skript geschrieben haben, ist dies nicht möglich.

Ich verstehe nicht wirklich was du meinst. Kannst du ein Beispiel posten? ein Arbeitsteil Code? Soweit ich weiß, arbeitet "$ {}" mit Variablen und macht Dinge wie "echo" $ _suffix "" möglich. Kamil Maciorowski vor 5 Jahren 1
genau über dem Beispiel mygrep () Yurij vor 5 Jahren 0