ksh93
hat Disziplinen, die typischerweise für solche Dinge verwendet werden. Mit zsh
könnten Sie die kapern dynamische genannte Verzeichnis - Funktion :
Definieren Sie zum Beispiel:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Und dann können Sie verwenden ~[incr]
, um $incr
jedes Mal ein Inkrement zu erhalten :
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Ihr Ansatz schlägt fehl, weil in head -1 /tmp/ints
, head das FIFO öffnet, einen vollständigen Puffer liest, eine Zeile druckt und sie dann schließt . Nach dem Schließen sieht das Schreibende ein gebrochenes Rohr.
Stattdessen können Sie entweder Folgendes tun:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ seq infinity > $fifo &
$ exec 3< $fifo
$ IFS= read -rneu3
1
$ IFS= read -rneu3
2
Dort lassen wir read
das Leseende auf fd 3 offen und lesen jeweils ein Byte, nicht einen vollen Puffer, um sicherzugehen, dass genau eine Zeile (bis zum Zeilenumbruchzeichen) gelesen wird.
Oder Sie könnten tun:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ while true; do echo $((++incr)) > $fifo; done &
$ cat $fifo
1
$ cat $fifo
2
Dieses Mal instanziieren wir für jeden Wert eine Pipe. Dies ermöglicht die Rückgabe von Daten, die eine beliebige Anzahl von Zeilen enthalten.
In diesem Fall wird jedoch cat
die echo
und die Schleife entsperrt, sobald das FIFO geöffnet wird, sodass mehr ausgeführt echo
werden kann, wenn cat
der Inhalt gelesen und die Pipe geschlossen wird (wodurch die nächste echo
eine neue Pipe instanziiert).
Eine echo
Problemumgehung könnte darin bestehen, eine Verzögerung hinzuzufügen, z. B. indem Sie eine externe Datei ausführen , wie von @jimmij vorgeschlagen, oder eine hinzufügen sleep
, aber das wäre immer noch nicht sehr robust, oder Sie könnten die benannte Pipe nach jeder neu erstellen echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Dadurch bleiben immer noch kurze Fenster, in denen die Pipe nicht vorhanden ist (zwischen " unlink()
erledigt von" rm
und " mknod()
erledigt von" mkfifo
), was cat
zu einem Fehler führt, und sehr kurze Fenster, in denen die Pipe instanziiert wurde, aber kein Prozess jemals wieder darauf schreibt (zwischen " write()
und") close()
erledigt durch echo
) bewirkt cat
, dass nichts zurückgegeben wird, und kurze Fenster, in denen die benannte Pipe noch vorhanden ist, aber nichts wird sie jemals zum Schreiben öffnen (zwischen close()
erledigt von echo
und unlink()
erledigt von rm
), wo cat
hängen bleibt.
Sie können einige dieser Fenster folgendermaßen entfernen :
fifo=~/.generators/incr
(
umask 077
mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo &&
while
mkfifo $fifo.new &&
{
mv $fifo.new $fifo &&
echo $((++incr))
} > $fifo
do : nothing
done
) &
Auf diese Weise besteht das einzige Problem darin, dass Sie mehrere Katzen gleichzeitig ausführen (alle öffnen das FIFO, bevor unsere Schreibschleife zum Schreiben bereit ist). In diesem Fall teilen sie die echo
Ausgabe.
Ich würde auch davon abraten, einen festen Namen, weltweit lesbare Fifos (oder eine andere Datei für diese Angelegenheit) in weltweit beschreibbaren Verzeichnissen /tmp
zu erstellen, es sei denn, es handelt sich um einen Dienst, der allen Benutzern im System zugänglich gemacht wird.
command echo
oder/bin/echo
statt eingebautecho
. Außerdem können Sie diesen Befehl etwas kürzer machen :repeat 999 /bin/echo $((++incr)) > /tmp/int &
.Wenn Sie Code ausführen möchten, wenn der Wert einer Variablen gelesen wird, können Sie dies nicht in zsh selbst tun. Die
RANDOM
Variable ist (wie andere ähnliche spezielle Variablen) im zsh-Quellcode fest codiert. Sie können jedoch ähnliche Sondergrößen definieren , indem ein Modul in C. Viele der Standard - Schreibmodule definieren spezielle Variablen.Sie können einen Coprozess verwenden , um einen Generator zu erstellen.
Dies ist jedoch ziemlich begrenzt, da Sie nur einen Coprozess haben können. Eine weitere Möglichkeit, schrittweise Ausgabe von einem Prozess zu erhalten , ist von einer Umleitung Prozess Substitution .
Beachten Sie, dass
head -1
dies hier nicht funktioniert, da ein ganzer Puffer gelesen, ausgedruckt und beendet wird. Die Daten, die aus der Pipe gelesen wurden, bleiben gelesen. Dies ist eine intrinsische Eigenschaft von Pipes (Sie können keine Daten wieder einfügen). Das integrierteread
System vermeidet dieses Problem, indem es jeweils ein Byte liest. Dadurch kann es angehalten werden, sobald es die erste neue Zeile findet, ist jedoch sehr langsam (das spielt natürlich keine Rolle, wenn Sie nur ein paar hundert Bytes lesen).quelle
bash
, siehe den Bash-Abschnitt unter diesem Link.coproc
Coprozesse, ich meine, keine leeren)coproc cmd1; exec 3>&p 4<&p; coproc cmd2 3>&- 4<&-...
Ich denke, ich würde es mit einem Signal tun.
Es funktioniert sowieso für mich.
In einem nur geringfügig verwandten Punkt ist hier etwas Seltsames, das ich neulich entdeckt habe:
Es wird auch seltsamer:
quelle
bash
das Verhalten geändert? Ich denke, die Aussage,pwd
nicht nur zu überprüfen und sich darauf zu beziehen,$PWD
ist falsch.mkdir /tmp/dir; cd $_; PS4='$OLDPWD, $PWD + '; set -x; OLDPWD=$OLDPWD PWD=$PWD command eval ' cd ..; cd ..; cd ~; pwd'; pwd; cd .; pwd
könnte dir zeigen, was ich meine. Es ist ein Problem, das mich mit diesemns()
Ding nervte .