stdout
昨日、にリダイレクトしようとしてかなりの時間を費やした後stdin
、私は次の方法に行き着きました。それは本当にいいことではありませんが、名前付きパイプ/FIFOソリューションよりも私はそれを好むと思います。
read | { P0 | ... | P(n-1); } >/dev/fd/0
これ{ ... } >/dev/fd/0
は、パイプシーケンス全体のstdoutをstdinにリダイレクトすることです(つまり、P(n-1)の出力をP0の入力にリダイレクトします)。使用>&0
または類似のものは機能しません。これはおそらく、bashが0
への書き込みを気にしないのに読み取り専用であると想定しているため/dev/fd/0
です。
最初のread
パイプが必要なのは、それがないと、入力ファイル記述子と出力ファイル記述子の両方が同じptsデバイス(少なくとも私のシステムでは)であり、リダイレクトは効果がないためです。(ptsデバイスはパイプとして機能しません。書き込みを行うと画面に表示されます。){ ... }
通常のパイプを入力することにより、リダイレクトは目的の効果をもたらします。
私のcalc
/square
例で説明するには:
function calc() {
# calculate sum of squares of numbers 0,..,10
sum=0
for ((i=0; i<10; i++)); do
echo $i # "request" the square of i
read ii # read the square of i
echo "got $ii" >&2 # debug message
let sum=$sum+$ii
done
echo "sum $sum" >&2 # output result to stderr
}
function square() {
# square numbers
read j # receive first "request"
while [ "$j" != "" ]; do
let jj=$j*$j
echo "square($j) = $jj" >&2 # debug message
echo $jj # send square
read j # receive next "request"
done
}
read | { calc | square; } >/dev/fd/0
上記のコードを実行すると、次の出力が得られます。
square(0) = 0
got 0
square(1) = 1
got 1
square(2) = 4
got 4
square(3) = 9
got 9
square(4) = 16
got 16
square(5) = 25
got 25
square(6) = 36
got 36
square(7) = 49
got 49
square(8) = 64
got 64
square(9) = 81
got 81
sum 285
もちろん、この方法はかなりのハックです。特に、このread
部分には望ましくない副作用があります。「実際の」パイプループの終了は、全体の終了にはつながりません。read
パイプループが終了したと判断できるのは、何かを書き込もうとすることでしか判断できないように思われるので、これ以上のことは考えられませんでした。