
他の2つのコマンドの出力を介してコマンドをパイプし、2つのプロセス置換結果をマージしようとしています。私を近づけた例は次のとおりです。
command | tee >(sed -rn 's/.*foo (bar).*/1/p') >(awk '{print $3}')
しかし、私は次の目標を達成したいと思います。
- 元のコマンドの入力ストリームを見る必要はありません。
- 「貼り付け」を使って結果をマージしたいです。
1つのオプションは、2つの別々のコマンドを実行してファイルに保存することですが、必要なほどエレガントではありません。 Bashでこれを行う最もエレガントな(1行、明確に理解されている)方法は何ですか?
答え1
元のコマンドの出力が表示される理由は、指定されたファイルだけでなくtee
出力によるものです。stdout
これを中止するには、この出力をコマンドの最後に入れるか、追加を追加して、>/dev/null
この出力をプロセス交換の1つにリダイレクトできます>
。たとえば、次のようになります。
command | tee >(sed -rn 's/.*foo (bar).*/1/p') > >(awk '{print $3}')
あるいは、より簡単に別のパイプを使用するだけです。
command | tee >(sed -rn 's/.*foo (bar).*/1/p') | awk '{print $3}'
結合された2つのプロセス置換を使用した結果については、paste
私が知らないあいまいなシェルトリックがない限り、名前付きパイプを使用せずにこれを行う方法はありません。最終的にこれは2つです(明確さを高めるためにフォーマットされています)。
mkfifo /tmp/myfifo
command |
tee >(sed -rn 's/.*foo (bar).*/1/p' >/tmp/myfifo) |
awk '{print $3}' |
paste /tmp/myfifo -
これをスクリプトに入れる場合は、一時的な名前付きパイプを作成するように提案を使用することも検討できます。ここ。
答え2
あなたがすべきことはですsed
。
command |
sed '/\([^ ][^ ]* *\)\{2\}/{h
s///;s/^ *//;s/ .*/p
g};s/.*foo \(bar\).*/\1/p;d'
しかし、他のものに関しては、tee
について文書|pipe
:
cmd1 | {
{ tee /dev/fd/3 |
cmd2 >&2
} 3>&1 |
cmd3
} 2>&1 |paste
しかし、すでに使用しているので、sed
次のように使用できます。賢い tee
必要に応じてコピー/リダイレクトしてください。
cmd | {
sed -n 'p;s/.*foo \(bar\).*/\1/w /dev/fd/3' |
awk ...
} 2>&1
答え3
IMHOよりエレガントで(明確に理解されている)「トリック」を避けてくださいtee
。 @mikeserv
はsed
。コマンドを使用したコマンド置換の例:awk
printf
$ printf "foo %s %s %s\n" {1..30}
foo 1 2 3
foo 4 5 6
foo 7 8 9
foo 10 11 12
foo 13 14 15
foo 16 17 18
foo 19 20 21
foo 22 23 24
foo 25 26 27
foo 28 29 30
要件(例):
貼り付け出力
sed -rn '/3/ s/[^ ]* ([^ ]*).*/\1/'
「3」の行のみを選択し、2番目のフィールドを取得します。
最初の数字は1、13、22、28の行です。awk 'NR>2 {print $3}'
すべての行の3番目のフィールドを表示
要件1のストリームは配列としてキャプチャされbar
、
要件2のストリームは配列としてキャプチャされますsecondstream
。
すべての入力が処理された後、キャプチャされたストリームをENDブロックに貼り付けます。
printf "foo %s %s %s\n" {1..30} |
awk '/3/ {bar[barcounter++]=$2}
NF>2 {secondstream[streamnr++]=$3}
END {for (i=0;i<streamnr;i++) print bar[i], secondstream[i];}
'
結果:
1 2
13 5
22 8
28 11
14
17
20
23
26
29