Wissen Sie, ich bin nicht davon überzeugt, dass Sie unbedingt eine sich wiederholende Rückkopplungsschleife benötigen, wenn Ihre Diagramme dargestellt werden. Vielleicht können Sie sogar eine dauerhafte Pipeline zwischen Koprozessen verwenden . Andererseits kann es sein, dass es keinen allzu großen Unterschied gibt - sobald Sie eine Zeile in einem Coprozess öffnen, können Sie typische Stilschleifen implementieren, in die nur Informationen geschrieben und daraus gelesen werden, ohne dass etwas ganz Besonderes getan wird.
Zunächst scheint es, dass dies bc
für Sie ein Hauptkandidat für einen Koprozess ist. In können bc
Sie define
Funktionen, die so ziemlich das tun können, was Sie in Ihrem Pseudocode verlangen. Zum Beispiel könnten einige sehr einfache Funktionen dazu so aussehen:
printf '%s()\n' b c a |
3<&0 <&- bc -l <<\IN <&3
a=1; b=0; c=0;
define a(){ "a="; return (a = c+1); }
define b(){ "b="; return (b = 3*a); }
define c(){ "c="; return (c = s(b)); }
IN
... was würde drucken ...
b=3
c=.14112000805986722210
a=1.14112000805986722210
Aber natürlich tut es nicht zuletzt . Sobald die für die Pipe zuständige Unterschale printf
beendet wird (direkt nach dem printf
Schreiben a()\n
in die Pipe), wird die Pipe abgerissen und bc
die Eingabe wird geschlossen und sie wird ebenfalls beendet. Das ist bei weitem nicht so nützlich, wie es sein könnte.
@derobert hat bereits erwähnten FIFO s , wie sie durch die Schaffung eines gehabt werden Named Pipe mit der Datei - mkfifo
Dienstprogramm. Dies sind im Wesentlichen auch nur Pipes, mit der Ausnahme, dass der Systemkern einen Dateisystemeintrag mit beiden Enden verbindet. Diese sind sehr nützlich, aber es wäre schöner, wenn Sie nur eine Pipe hätten, ohne zu riskieren, dass sie im Dateisystem beschnüffelt wird.
Wie es passiert, macht Ihre Shell dies oft. Wenn Sie eine Shell verwenden, die die Prozessersetzung implementiert , haben Sie ein sehr einfaches Mittel, um eine dauerhafte Pipe zu erhalten - die Art, die Sie möglicherweise einem Hintergrundprozess zuweisen, mit dem Sie kommunizieren können.
In bash
zum Beispiel können Sie sehen , wie die Prozess Substitution Werke:
bash -cx ': <(:)'
+ : /dev/fd/63
Sie sehen, es ist wirklich eine Substitution . Die Shell ersetzt während der Expansion einen Wert, der dem Pfad zu einer Verbindung zu einer Pipe entspricht . Sie können das ausnutzen - Sie müssen nicht gezwungen sein, diese Pipe nur zu verwenden, um mit dem Prozess zu kommunizieren, der in der ()
Substitution selbst abläuft ...
bash -c '
eval "exec 3<>"<(:) "4<>"<(:)
cat <&4 >&3 &
echo hey cat >&4
read hiback <&3
echo "$hiback" here'
... was druckt ...
hey cat here
Jetzt weiß ich, dass verschiedene Shells das Coprozess- Ding auf unterschiedliche Weise ausführen - und dass es eine bestimmte Syntax bash
für das Einrichten eines (und wahrscheinlich auch einer zsh
) gibt -, aber ich weiß nicht, wie diese Dinge funktionieren. Ich weiß nur, dass Sie die obige Syntax verwenden können, um praktisch dasselbe zu tun, ohne das Rigmarole in beiden bash
und zsh
- und Sie können eine sehr ähnliche Sache in hier-Dokumenten tundash
und busybox ash
den gleichen Zweck mit hier-Dokumenten erreichen (weil dash
und busybox
hier- Dokumente mit Pipes anstelle von temporären Dateien (wie die beiden anderen) .
Also, wenn angewendet auf bc
...
eval "exec 3<>"<(:) "4<>"<(:)
bc -l <<\INIT <&4 >&3 &
a=1; b=0; c=0;
define a(){ "a="; return (a = c+1); }
define b(){ "b="; return (b = 3*a); }
define c(){ "c="; return (c = s(b)); }
INIT
export BCOUT=3 BCIN=4 BCPID="$!"
... das ist der schwierige Teil. Und das ist der lustige Teil ...
set --
until [ "$#" -eq 10 ]
do printf '%s()\n' b c a >&"$BCIN"
set "$@" "$(head -n 3 <&"$BCOUT")"
done; printf %s\\n "$@"
... was druckt ...
b=3
c=.14112000805986722210
a=1.14112000805986722210
#...24 more lines...
b=3.92307618030433853649
c=-.70433330413228041035
a=.29566669586771958965
... und es läuft noch ...
echo a >&"$BCIN"
read a <&"$BCOUT"
echo "$a"
... was mir nur den letzten Wert für bc
's gibt, a
anstatt die a()
Funktion aufzurufen , um ihn zu erhöhen und zu drucken ...
.29566669586771958965
Es wird in der Tat so lange weiterlaufen, bis ich es töte und seine IPC-Rohre abreiße ...
kill "$BCPID"; exec 3>&- 4>&-
unset BCPID BCIN BCOUT