さまざまなアプリケーションに同じパイプラインを使用したいです。たとえば、次のようになります。
cat my_file | {
cmd1
cmd2
cmd3
}
Cmd1は入力の一部を消費する必要があります。 Cmd2は他の部分を消費しなければなりません。
ただし、各コマンドはより多くの入力を消費するため、読み取った内容を適切にバッファリングする必要があります。
たとえば、
yes | nl | {
head -n 10 > /dev/null
cat
} | head -n 10
11行ではなく912行から出力されます。
Teeは、各コマンドが標準入力の一部を消費する必要があるため、良い選択ではありません。
動作させる簡単な方法はありますか?
ベストアンサー1
tee
ストリーム全体を処理するためにコマンドをコピーするために使用できるいくつかのコマンドがあります。
( ( seq 1 10 | tee /dev/fd/5 | sed s/^/line..\ / >&4 ) 5>&1 | wc -l ) 4>&1
line.. 1
line.. 2
line.. 3
line.. 4
line.. 5
line.. 6
line.. 7
line.. 8
line.. 9
line.. 10
10
または、bashを使用して1行ずつ分割します。
while read line ;do
echo cmd1 $line
read line && echo cmd2 $line
read line && echo cmd3 $line
done < <(seq 1 10)
cmd1 1
cmd2 2
cmd3 3
cmd1 4
cmd2 5
cmd3 6
cmd1 7
cmd2 8
cmd3 9
cmd1 10
最後に実行する方法があり、cmd1
一cmd2
度cmd3
だけフローの3分の1標準入力:
( ( ( seq 1 10 |
tee /dev/fd/5 /dev/fd/6 |
sed -ne '1{:a;p;N;N;N;s/^.*\n//;ta;}' |
cmd1 >&4
) 5>&1 |
sed -ne '2{:a;p;N;N;N;s/^.*\n//;ta;}' |
cmd2 >&4
) 6>&1 |
sed -ne '3{:a;p;N;N;N;s/^.*\n//;ta;}' |
cmd3 >&4
) 4>&1
command_1: 1
command_1: 4
command_1: 7
command_1: 10
Command-2: 2
Command-2: 5
Command-2: 8
command 3: 3
command 3: 6
command 3: 9
これを試すには、次のものを使用できます。
alias cmd1='sed -e "s/^/command_1: /"' \
cmd2='sed -e "s/^/Command_2: /"' \
cmd3='sed -e "s/^/Command_3: /"'
同じスクリプトで別のプロセスでストリームを使用したい場合は、次のことができます。
(
for ((i=(RANDOM&7);i--;));do
read line;
echo CMD1 $line
done
for ((i=RANDOM&7;i--;));do
read line
echo CMD2 $line
done
while read line ;do
echo CMD3 $line
done
)
CMD1 1
CMD1 2
CMD1 3
CMD2 4
CMD2 5
CMD2 6
CMD2 7
CMD2 8
CMD2 9
CMD3 10
これを行うには、別のスクリプトを次のように変換する必要があります。バッシュ機能モノリシックスクリプトを書く能力。
別のアプローチは、各スクリプトが何も出力しないようにすることです。標準出力cat
、チェーンそれらを:
#!/bin/sh
for ((i=1;1<n;i++));do
read line
pRoCeSS the $line
echo >output_log
done
cat
最終的なコマンドは次のとおりです。
seq 1 10 | cmd1 | cmd2 | cmd2