web-dev-qa-db-ja.com

シェルで複数のファイルにパイプする

ディスクに保存したくない大量のデータを生成するアプリケーションがあります。アプリケーションは、ほとんどの場合、使用したくないデータを出力しますが、個別のファイルに分割する必要がある一連の有用な情報を出力します。たとえば、次の出力があるとします。

JUNK
JUNK
JUNK
JUNK
A 1
JUNK
B 5
C 1
JUNK

次のようにアプリケーションを3回実行できます。

./app | grep A > A.out
./app | grep B > B.out
./app | grep C > C.out

これは私が欲しいものを手に入れますが、時間がかかりすぎます。また、すべての出力を1つのファイルにダンプし、それを解析したくありません。

上記の3つの操作を組み合わせて、アプリケーションを1回実行するだけで3つの個別の出力ファイルを取得できるようにする方法はありますか?

29
sj755

Tシャツをお持ちの場合

./app | tee >(grep A > A.out) >(grep B > B.out) >(grep C > C.out) > /dev/null

(から ここ

プロセス置換について

78
Aurélien Ooms

awkを使用できます

./app | awk '/A/{ print > "A.out"}; /B/{ print > "B.out"}; /C/{ print > "C.out"}'
32
Rahul Patil

シェルの パターンマッチング機能 を使用することもできます。

./app | while read line; do 
     [[ "$line" =~ A ]] && echo $line >> A.out; 
     [[ "$line" =~ B ]] && echo $line >> B.out; 
     [[ "$line" =~ C ]] && echo $line >> C.out; 
 done

あるいは:

./app | while read line; do for foo in A B C; do 
     [[ "$line" =~ "$foo" ]] && echo $line >> "$foo".out; 
  done; done

-で始まるバックスラッシュと行を処理できるより安全な方法:

./app | while IFS= read -r line; do for foo in A B C; do 
     [[ "$line" =~ "$foo" ]] && printf -- "$line\n" >> "$foo".out; 
  done; done

@StephaneChazelasがコメントで指摘しているように、これはあまり効率的ではありません。最善の解決策はおそらく @AurélienOoms ' です。

17
terdon

複数のコアがあり、プロセスを並列にしたい場合は、以下を実行できます。

parallel -j 3 -- './app | grep A > A.out' './app | grep B > B.out' './app | grep C > C.out'

これにより、並列コアで3つのプロセスが生成されます。コンソールまたはマスターファイルへの出力が必要な場合は、出力を混合するよりも、特定の順序で出力を維持できるという利点があります。

Ole Tangeのgnuユーティリティparallelは、ほとんどのリポジトリからparallelまたはという名前で入手できます。moreutils 。ソースは Savannah.gnu.org から取得できます。また、紹介用のビデオは here です。

補遺

Parallelの最新バージョン(ディストリビューションリポジトリのバージョンとは限りません)を使用すると、よりエレガントな構成を使用できます。

./app | parallel -j3 -k --pipe 'grep {1} >> {1}.log' ::: 'A' 'B' 'C'

これは、1つの./appと3つの並列grepプロセスを別々のコアまたはスレッドで実行した結果を実現します(並列自体によって決定されるように、-j3もオプションであると見なされますが、この例では説明のために提供されています)。

新しいバージョンのparallelは、次のようにして取得できます。

wget http://ftpmirror.gnu.org/parallel/parallel-20131022.tar.bz2

次に、通常の解凍、cd to parallel- {date}、。/ configure && make、Sudo make install。これにより、Parallel、Man Page Parallel、Man Page Parallel_tutorialがインストールされます。

9
AsymLabs

これはPerlの1つです:

./app | Perl -ne 'BEGIN {open(FDA, ">A.out") and 
                         open(FDB, ">B.out") and 
                         open(FDC, ">C.out") or die("Cannot open files: $!\n")} 
                  print FDA $_ if /A/; print FDB $_ if /B/; print FDC $_ if /C/'
7
troydj
sed -ne/A/w\ A.out -e/B/w\ B.out -e/C/p <in >C.out

... if<inは読み取り可能です。3つの出力ファイルはすべて、何かが書き込まれる前に切り捨てられます。

1
mikeserv