回答:
awk
あなたが行うことができます。
awk '{print >out}; /XYZ/{out="file2"}' out=file1 largefile
説明:最初のawk
引数(out=file1
)は、後続の引数(largefile
)の処理中に出力に使用されるファイル名を持つ変数を定義します。awk
プログラムは変数で指定したファイルにすべての行を印刷しますout
({print >out}
)。パターンXYZ
が見つかると、出力変数は新しいファイル({out="file2}"
)を指すように再定義され、後続のデータ行を印刷するためのターゲットとして使用されます。
参照:
これは仕事ですcsplit
:
csplit -sf file -n 1 large_file /XYZ/
うs
ilently前で作品を作成、ファイルを分割f
IX file
とn
一桁を使用してumbered、例えばfile0
使用していることを注意など/regex/
に分割しますが、一致していることを行を含めませんregex
。分割すると、ラインのマッチングを含むregex
追加+1
のオフセット:
csplit -sf file -n 1 large_file /XYZ/+1
これは、2つのファイルを作成し、 file0
そしてfile1
。絶対に名前file1
をfile2
付ける必要があり、常に空のパターンをcsplit
コマンドに追加して最初のファイルを削除できる場合:
csplit -sf file -n 1 large_file // /XYZ/+1
作成しfile0
、file1
そしてfile2
しかしfile0
、あなたが安全に取り外すことができるように空です:
rm -f file0
モダンksh
でsed
は、sed
上記の回答のいずれかのシェルバリアントがあります(つまり、なし)。
{ read in <##XYZ ; print "$in" ; cat >file2 ;} <largefile >file1
そして、ksh
単独での別のバリアント(つまり、省略cat
):
{ read in <##XYZ ; print "$in" ; { read <##"" ;} >file2 ;} <largefile >file1
(純粋なksh
ソリューションは非常にパフォーマンスが高いようです。2.4GBのテストファイルでは、sed
/ cat
ベースのアプローチでは39〜47秒でしたが、19〜21秒かかりました)。
read
し、print
あなたはちょうどそれがすべて独自の出力に行かせなければなりません- 。ASTツールキットを完全にビルドし、すべてのksh
ビルトインをコンパイルするとパフォーマンスが向上しますsed
。実際には、それらの1つではないのは奇妙なことです。しかし、while <file do
私はあなたがsed
そんなに必要としないと思うようなもので
awk
あなたのベンチマークでどのようにパフォーマンスしましたか?そして、私はksh
おそらくこの戦いに常に勝つと確信していsed
ますが、GNU を使用している場合、あなたはあまり公平ではありません-GNU sed
の-u
nbufferedは、プログラムの終了時に記述子のオフセットを残すPOSIXLYへの小便なアプローチですそれ-プログラムの通常の動作を遅くする必要はないはずです-バッファリングは問題ありsed
ません- 完了したら記述子をlseekするだけです。何らかの理由で、GNUはその考え方を覆します。
while
。印刷は、<##
リダイレクト演算子の定義された副作用として暗黙的に行われます。そして、一致する行のみが印刷を必要とします。(このようにシェル機能の実装はincl./exclをサポートするために最も柔軟性があります。)明示的なwhile
ループは大幅に遅くなると予想されます(ただし、チェックしていません)。
head
代わりに試しましたread
; 少し遅いように見えますが、より簡潔なコードです{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
。
簡単なハックは、ターゲットパターンが一致したかどうかに応じて、STDOUTまたはSTDERRに出力することです。その後、シェルのリダイレクト演算子を使用して、それに応じて出力をリダイレクトできます。たとえば、Perlでは、入力ファイルが呼び出さf
れ、2つの出力ファイルがf1
とf2
:
分割パターンに一致する行を破棄します。
perl -ne 'if(/XYZ/){$a=1; next} ; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2
一致した行を含める:
perl -ne '$a=1 if /XYZ/; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2
または、別のファイルハンドルに印刷します。
分割パターンに一致する行を破棄します。
perl -ne 'BEGIN{open($fh1,">","f1");open($fh2,">","f2");}
if(/XYZ/){$a=1; next}$a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
一致した行を含める:
perl -ne 'BEGIN{open($fh1,">","f1"); open($fh2,">","f2");}
$a=1 if /XYZ/; $a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
XYZ
ラインが出力にか含まれて?