画面に書き込むことなく結果を複数のコマンドにパイプ

画面に書き込むことなく結果を複数のコマンドにパイプ

解凍したい非常に大きなzipファイル(〜10 GB)があり、その結果は2つのコマンドで渡される必要があります。 2つの後続のコマンドの結果をファイルに追加する必要があります。

現在私は走っています

unzip -p bigFile.zip | head -n 1 >> output.txt
unzip -p bigFile.zip | grep -v 'skipLine' >> output.txt

これは約100万行を提供します。もう一行にしたいです。使い始めtee

unzip -p bigFile.zip | tee >(head -n 1 >> output.txt) >(grep -v 'skipLine' 
>> output.txt)

ただし、output.txtファイルには51行しか含まれておらず、最後の行は完全ではありません。また、後者のコマンドは、私が望んでいない結果を端末に印刷します。

私も試しました

unzip -p bigFile.zip | tee >(head -n 1 >> output.txt) | grep -v 'skipLine' 
>> output.txt

しかし、残念ながらこれも機能しません。

どんな助けでも大変感謝します!を使用する必要はありません。ウィジェットの出力をandコマンドにtee渡すことができる限り、他のコマンドはうまく機能します。unzipheadgrep

編集する:headそして、コマンドの出力を「結合」してから渡すことができれば、はるかにgrep良いでしょうzip。可能ですか?

答え1

最初の行を取得して印刷し、grepが残りの部分を使用できるようにするシェルスクリプトを解凍してパイプすることができます。

unzip -p bigFile.zip | {
    IFS= read -r header       # consume the first line, verbatim
    printf "%s\n" "$header"
    grep -v 'skipLine' 
} >> output.txt

ブロックから印刷された内容はすべて出力ファイルに追加されます。

答え2

2つの個別のコマンドをパイプする方法は考えられませんが、次のものを使用できますawk

unzip -p file.zip | awk 'NR==1 || !/skipLine/' > output

NR==1awkコマンドは、現在の行が最初の行()または一致しない場合skipline()を印刷します。!/skipLine

私が考えることができる最高の組み合わせgrepは次のとおりですhead

unzip -p file.zip | tee >(head -n1 > output) | tail -n+2 | grep -v skipLine >> output

アイデアは、最初の行を最初にキャプチャし、次をhead -n1使用してtail -n+2最初の行を除くすべてを印刷することです。grepawk

答え3

微妙な点が欠けている可能性がありますが、最初の行を維持し、最初の行以降に一意のテキストが含まれていない内容を維持したいと思いますskipLinesedこれをうまく処理するようです。

#!/bin/bash
sed -n '1 {p;d}         #for line 1, print and discard
        /skipLine/d     #delete any line with skipLine
        p               #print remainder
' << End_of_SampleData
head
prefix skipLine
keepLine
skipLine suffix
keepLine
End_of_SampleData

出力:

head
keepLine
keepLine

unzip -p bigFile.zip | sed ...このテストケースが要件を満たしている場合は、データをこのスクリプトにパイプできます。実行するプロセスはunzip1 つだけなので、高速化する必要があります。sed

答え4

コマンドには2つの問題がありますtee

tee >(head -n 1 >>output.txt) >(grep -v 'skipLine' >>output.txt)

最も簡単なのは、出力を削除したい場合です。これを行うには、単に標準出力を/ dev / nullに送信するだけです。

tee >(head -n 1 >>output.txt) >(grep -v 'skipLine' >>output.txt) >/dev/null

しかし、これは無駄なようです。tee2番目のコマンドを標準出力に接続する方が効率的です。

tee >(head -n 1 >>output.txt) | grep -v 'skipLine' >>output.txt

2つ目は、head必要な入力を読んだ後に閉じることです。簡単な修正は、入力を削除する手順を使用することです。

tee >(head -n 1 >>output.txt; dd of=/dev/null) | grep -v skipLine >>output.txt

このパイプが古いコンテンツを置き換えるようにするには、2つのオープンをoutput.txt1つに置き換えることができます。

exec 3>output.txt
tee >(head -n 1 >&3; dd of=/dev/null) | grep -v skipLine >&3

2つの独立したパイプを持つ初期バージョンとは異なり、これらのすべてのバージョンでは、ヘッダー行が出力ファイルの先頭にあるという保証はありません。これが要件の場合は、交換に対する他の答えの1つを確認してください(または以前のsleepシーケンスを使用したギャンブルgrep)。

しかし、この答えが役立つことを願っています。理解するなぜスプーンで食い込んでくれる代替案の代わりに、自分がすることの結果を見ることができるのでしょうか。

関連情報