$RANDOM
特殊変数はアクセスされるたびに新しい値を持ちます。この点で、これはいくつかの言語の「ジェネレータ」オブジェクトを連想させます。
でこのようなものを実装する方法はありますかzsh
?
そのために名前付きパイプを試しましたが、「ジェネレータ」プロセスを終了せずに制御された方法でFIFOからアイテムを抽出する方法が見つかりませんでした。たとえば、
% mkfifo /tmp/ints
% (index=0
while ( true )
do
echo $index
index=$(( index + 1 ))
done) > /tmp/ints &
[1] 16309
% head -1 /tmp/ints
0
[1] + broken pipe ( index=0 ; while ( true; ); do; echo $index; index=$(( ...
zshでこれらのジェネレータ型オブジェクトを実装する他の方法はありますか?
編集:これはうまくいきません:
#!/usr/bin/env zsh
FIFO=/tmp/fifo-$$
mkfifo $FIFO
INDEX=0
while true; do echo $(( ++INDEX )) > $FIFO; done &
cat $FIFO
上記の内容をスクリプトに入れて実行すると、期待した行が出力されることはほとんどありません。
1
代わりに、通常は複数の整数で構成されます。
1
2
3
4
5
生成される行数は実行ごとに異なります。
EDIT2:jimmijが指摘したようにに変更するとecho
効果/bin/echo
があります。
ベストアンサー1
ksh93
この種の仕事に一般的に使用される分野があります。それでzsh
誘拐できます。動的に名前が付けられたディレクトリ特徴:
定義例:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
その後、次を使用して毎回増分できます~[incr]
。$incr
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
ヘッドでhead -1 /tmp/ints
fifoを開き、バッファ全体を読み、1行を印刷し、それから閉じる。一度閉じると、書き込み側に壊れたパイプが表示されます。
代わりに、次のようにすることができます。
$ 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
ここでは、fd 3の読み込み端を開いたままにして、完全なread
バッファを読み込むのではなく、一度に1バイトずつ読みます(改行文字まで)。
またはこれを行うこともできます:
$ 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
この時点で、各値のパイプをインスタンス化します。これにより、任意の数の行を含むデータを返すことができます。
ただし、この場合、cat
fifoが開かれるとecho
ループがブロック解除されるため、echo
内容を読み取り、パイプが閉じられている間により多くのタスクを実行できます(新しいパイプの次のインスタンス化につながります)。cat
echo
回避策は、echo
@jimmijが提案したように、外部の実行やいくつかの追加などのいくつかの遅延を追加することですが、sleep
まだ強力ではないか、各項目の後に名前付きパイプを再作成できますecho
。
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
これにより、パイプが存在しない短いウィンドウ(unlink()
完成者rm
とmknod()
完成者の間mkfifo
)が依然としてcat
失敗を引き起こし、パイプがインスタンス化されたがプロセスが書き戻されない非常に短いウィンドウが残ります(完成者と完成者のwrite()
間close()
)完成者)は何もありません返さecho
れcat
ず、名前付きパイプがまだ存在するが書き込み用に何も開かない短いウィンドウ(close()
完了者echo
とunlink()
完成者の間rm
)cat
が中断されます。
その一部を削除できますWindowsこれにより:
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
) &
このように、唯一の問題は、複数のcatを同時に実行することです(書き込みループが書き込み用にfifoを開く準備ができる前にすべてfifoを開きます)。この場合、出力を共有しますecho
。
/tmp
また、システム内のすべてのユーザーに公開されているサービスでない限り、誰でも書き込むことができるディレクトリに、固定名の誰でも読むことができるfifo(またはその問題のすべてのファイル)を作成しないことをお勧めします。