どうを送りたいので、標準出力に出力の一工程で複数のプロセスを用いた好ましくは名前のない管Unix(Windows)?
質問
私はリダイレクトの標準出力に出力プロセスproc1二つのプロセスproc2とproc3:
proc2 -> stdout
/
proc1
\
proc3 -> stdout
てみました
proc1 | (proc2 & proc3)
が見られるとは思えませんの作業、すなわち
echo 123 | (tr 1 a & tr 1 b)
書き込みます
b23
標準出力に出力ではなく
a23
b23
解決
編集部注:
- >(…)
は 代替工程 である 標準外のシェルの特徴 の 一部の POSIX互換の貝殻: bash
, ksh
, zsh
.
-この答えを誤って送信出力処置換の出力のパイプライン すぎ: echo 123 | tee >(tr 1 a) | tr 1 b
.
-出力は、工程現場からの置換するunpredictablyインターリーブ、合を除き、 zsh
, のパイプラインの終了することができます前にコマンド内 >(…)
います。
Unix(またはmacを使用 tee
コマンド:
$ echo 123 | tee >(tr 1 a) >(tr 1 b) >/dev/null
b23
a23
通常ことはできませ tee
へのリダイレクト出力を複数のファイルが利用>(...)まで
リダイレクトを別の工程です。なので、一般的に、
$ proc1 | tee >(proc2) ... >(procN-1) >(procN) >/dev/null
いと考えている。
Windowsは思えないのシェルには等価です。Microsoftの Windows PowerShell は tee
コマンドになってる。
他のヒント
のようにdF、 bash
での利用 >(…)
構築の実行コマンドのファイル名を指定します。(あるもの <(…)
の構築を代行する 出力 他のコマンドのファイル名が、それは無関係で、今はもう完全性).
いbashや走行システムの古いバージョンのbashできな手で何bashは、FIFOのファイルです。
の一般的な方法で実現したいものは:
- 設定を変更するプロセスを受けるべきであり、出力のコマンドは、多くのFifo、好ましくは、グローバルフォルダ:
subprocesses="a b c d" mypid=$$ for i in $subprocesses # this way we are compatible with all sh-derived shells do mkfifo /tmp/pipe.$mypid.$i done
- 開始すべてのサブプロセスを待ってから入力したFifo:
for i in $subprocesses do tr 1 $i </tmp/pipe.$mypid.$i & # background! done
- 実行を行うコマンドteeingのFifo:
proc1 | tee $(for i in $subprocesses; do echo /tmp/pipe.$mypid.$i; done)
- 最後に、削除のFifo:
for i in $subprocesses; do rm /tmp/pipe.$mypid.$i; done
注意:互換性の理由で入っていて、 $(…)
とbackquotesが、それが出来なかったこの答えにbackquote使用します。通常、 $(…)
れるのは仕事でも、古いバージョンのkshがっていることを確認してくださいませた上で封の …
部backquotes.
Unix(bash
, ksh
, zsh
)
dFの回答 を含む 種子 の回答に基づく tee
や 出力 処置換
(>(...)
) ません 作業によっては、お客様の要件:
注そのプロセスの置換をして 標準外の 機能を中心)
POSIXには-特徴-み殻などの dash
(ある行為として /bin/sh
Ubuntu,
のためのインスタンス)、 ない ます。シェルスクリプトを対象に /bin/sh
すべ ない に依存します。
echo 123 | tee >(tr 1 a) >(tr 1 b) >/dev/null
の 落とし穴 このアプローチ:
予測できないので、非同期出力動作:の出力ストリームからのコマンドの出力処理が置換
>(...)
interleaveが予想する。に
bash
やksh
(zsh
が参照例外):- 出力の場合は到着 後 のコマンドは終了いたしました。
- その後のコマンドが実行 前 コマンドは、その置換が完了して -
bash
やksh
い ない の出力処理が置換-普プロセスに仕上がりは、少なくともデフォルトです。 - jmb でもコメントdFの回答:
このコマンドを始めた内部
>(...)
酵元のシェルで、簡単かを判定するのに合わない場合はご相談ください;のtee
仕上がりになり書きを全てのものに置換されたプロセスが消費のデータから様々なバッファーをカーネルおよびファイルI/O、何時間は内部データの取り扱い.できるとの出会いは競合状態が外殻を頼りになされたサブプロセス。
zsh
は、このときシェル は デフォルトのプロセスの出力処理の置換に仕上がり, を除く であれば stderr このリダイレクトされ一2> >(...)
).ksh
(少なくともバージョン93u+
)は使用できるの引数は以下のwait
待つの出力処理が置換-普プロセスに仕上がります。
るということに注意してくださるインタラクティブセッションを待たず申請中 背景に雇用 もしています。bash v4.4+
できるのを待つ 最近では 開始出力処理で代用することwait $!
, ものの、引数以下のwait
は ない ですが、このに適しないコマンド 複数の 出力処理が置換.しかし、
bash
やksh
可 強制 待 による配管のコマンド| cat
, なお、このコマンドを実行される 独立したサブシェルで. 注意:ksh
(ksh 93u+
)をサポートしていない送信 stderr 出力処置換(2> >(...)
);このような試みが 無視され.ながら
zsh
(commendably)同期 デフォルト のり) 標準出力に出力 出力処理が置換もの| cat
技術はできなく同期と stderr 出力処理ャ2> >(...)
).
しかし、 場合でもすることを保証するため 同期実行, の問題 unpredictablyインターリーブ出力 が残っています。
以下のコマンドが実行 bash
または ksh
, この問題行動(すでに数回見る 両 症状):の AFTER
は通常の印刷 前 出力から出力置換の出力から、後者はインターリーブunpredictably.
printf 'line %s\n' {1..30} | tee >(cat -n) >(cat -n) >/dev/null; echo AFTER
短:
保証の特定の単コマンドの出力配列:
- も
bash
もksh
もzsh
支援す。
- も
同期の実行:
- 可もしくは stderr-仕入出力処理が置換:
- に
zsh
, り出されるとのことであっ 常 非同期。 - に
ksh
, い 働いていない全.
- に
- 可もしくは stderr-仕入出力処理が置換:
まとともに暮らしながらこれらの制限は、出力処理の置換を実行可能なオプション(例えば、すべての書分離出力ファイル).
ご注意 tzotのも面倒なものの、潜在的にPOSIXに準拠した溶液 も展示予想外の出力動作;しかし、よ wait
することを保証できるその後のコマンドを起動しない実行までのすべての背景-プロセスは終了いたしました。
参照下 のための より強固な同期,直列化された出力を実施.
のみ 簡単な bash
液 と予測可能な出力動作 にし、 非常に遅く大きな入力設定, ので、シェルのループは、本質的に遅くなります。
また、この 交互 出力ラインからの対象コマンド.
while IFS= read -r line; do
tr 1 a <<<"$line"
tr 1 b <<<"$line"
done < <(echo '123')
Unixを使用GNU並列)
の設置 GNU parallel
が可能 強固なソリューション と 直列化された(単コマンド)の出力 るまで ルチコアcpuを生かして並列実行:
$ echo '123' | parallel --pipe --tee {} ::: 'tr 1 a' 'tr 1 b'
a23
b23
parallel
デフォルトで確実に出力からコマンドなinterleave(この動作を変更できる見 man parallel
).
注意:一部のLinux distros付 異なる parallel
明るいはコマンドにより、以下の使用 parallel --version
るかを決定した場合です。
Windows
ジェイBazuziのも答え 表示方法を示しな PowerShell.とはいえ:彼の答えは、アナログのループを bash
答えでき 非常に遅く大きな入力設定 とも 交互 出力ラインからの対象コマンド.
bash
に基づくものの、その他の携帯Unix液同期実行、出力の直列化
以下は、シンプルですが合理的に実施アプローチを発表 tzotの回答 たまた提供:
- 同期実行
- 直列化され(グループ化)の出力
ないものを厳重にPOSIX準拠したものであり、 bash
スクリプトで行うべき 携帯載のUnixプラットフォーム bash
.
注意:べき本格的な実施を発売、MITライセンスの下で この概要.
保存されると以下のコードとしてスクリプト fanout
, で実行可能なけintご PATH
, 、コマンドからの疑問に思うとしており
$ echo 123 | fanout 'tr 1 a' 'tr 1 b'
# tr 1 a
a23
# tr 1 b
b23
fanout
スクリプトのソースコード:
#!/usr/bin/env bash
# The commands to pipe to, passed as a single string each.
aCmds=( "$@" )
# Create a temp. directory to hold all FIFOs and captured output.
tmpDir="${TMPDIR:-/tmp}/$kTHIS_NAME-$$-$(date +%s)-$RANDOM"
mkdir "$tmpDir" || exit
# Set up a trap that automatically removes the temp dir. when this script
# exits.
trap 'rm -rf "$tmpDir"' EXIT
# Determine the number padding for the sequential FIFO / output-capture names,
# so that *alphabetic* sorting, as done by *globbing* is equivalent to
# *numerical* sorting.
maxNdx=$(( $# - 1 ))
fmtString="%0${#maxNdx}d"
# Create the FIFO and output-capture filename arrays
aFifos=() aOutFiles=()
for (( i = 0; i <= maxNdx; ++i )); do
printf -v suffix "$fmtString" $i
aFifos[i]="$tmpDir/fifo-$suffix"
aOutFiles[i]="$tmpDir/out-$suffix"
done
# Create the FIFOs.
mkfifo "${aFifos[@]}" || exit
# Start all commands in the background, each reading from a dedicated FIFO.
for (( i = 0; i <= maxNdx; ++i )); do
fifo=${aFifos[i]}
outFile=${aOutFiles[i]}
cmd=${aCmds[i]}
printf '# %s\n' "$cmd" > "$outFile"
eval "$cmd" < "$fifo" >> "$outFile" &
done
# Now tee stdin to all FIFOs.
tee "${aFifos[@]}" >/dev/null || exit
# Wait for all background processes to finish.
wait
# Print all captured stdout output, grouped by target command, in sequences.
cat "${aOutFiles[@]}"
年@dF:うユーティは思ったので思表示をすることでユー.
PS > "123" | % {
$_.Replace( "1", "a"),
$_.Replace( "2", "b" )
}
a23
1b3
注各オブジェクトの最初のコマンドを処理し、次のオブジェクトが作成されます。これをスケーリングには大型用の入力端子が付いています。
別の言い方ないです
eval `echo '&& echo 123 |'{'tr 1 a','tr 1 b'} | sed -n 's/^&&//gp'`
出力:
a23
b23
作成不要独立したサブシェルでこちら