2016-01-06 3 views
6

内のフィールドに一致する行を削除します。各ファイルの行は同一ではありませんが、同一のフィールドのサブセットがあります。私は、file1の各行からフィールド3-5を取り込み、同じパターン(同じ3つのフィールド、file2の2番目から4番目のフィールド)にfile2を検索します。一致するものが見つかった場合は、file1から対応する行を削除します。のawk/sedの/ grepの私はいくつかの行(十)がFILE1、およびはるかに長いFILE2(〜50万ライン)を持っている別のファイル

例えば、FILE1:

2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current 
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current 
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt 
2016-01-06T07:53:50 2016-01-06T07:52:14 2016006 090E A TM Current 
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current 

FILE2:(50万ライン用とオン)

2016-01-06T07:35:06.87 2016003 100E C NN Current 0 
2016-01-06T07:35:09.97 2016003 100E B TM Current 6303 
2016-01-06T07:36:23.12 2016004 030N C TM Current 0 
2016-01-06T07:37:57.36 2016006 090E A TM Current 399 
2016-01-06T07:40:29.61 2016006 010N C TM Current 0 

...

したがって、この場合には、私は四行目を削除したいですfile1の(その場で)。

次は私が削除したい行見つける:

grep "$(awk '{print $3,$4,$5}' file1)" file2 

をだから、一つの解決策は、これはsedのためにパイプにかもしれないが、私はパイプで連結された入力からのsedでの照合パターンを設定するかは不明です。そして、オンラインで検索するとawkはおそらくこのすべて(またはおそらくsedなど)を行うことができるので、きれいなソリューションがどのように見えるのか疑問に思うかもしれません。他のプロセスが、これが起こっている間に、ファイルを変更しようとする可能性があるため、

はまた、速度が(私はこれがより多くの合併症を提示することができる知っている...)やや重要です。一致は一般的に、最初からではなく、file2の最後にあります(file2を下から上に検索する方法がある場合)。

+0

pluse-UNO任意のUNIXコマンドで

は、あなただけ行う元のファイルを上書きします。投稿と幸運を続けてください。 – shellter

答えて

4
$ awk 'NR==FNR{file2[$2,$3,$4]; next} !(($3,$4,$5) in file2)' file2 file1 
2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current 
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current 
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt 
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current 

FILE2 50万行が含まれているという事実は、awkのWRTメモリや実行速度のために問題になりません - それは最悪の場合でも、約1秒以内に完了する必要があります。この場合はそう

cmd file > tmp && mv tmp file 

:良好のような問題のため

awk '...' file2 file1 > tmp && mv tmp file1 
+0

ありがとうございます。私はこれがどのように機能するかを見ていて、かなり速いです。私はそれを逆にしようとしていましたが、file1を配列に読み込むことはできませんでしたが、file1の行をどのように出力するのかが分かりません。 – trid3

+0

これで、file1を配列に読み込むことが間違ったアプローチであることがわかりました。そうすることでメモリが節約されますが、file1の配列全体を1回のファイル2の行ごとに1回ループする必要があります。そのため、スクリプトの実行に要する時間が、行数の倍数file1。 –

+0

例えば、次のようなものです:awk 'NR == FNR {file1 [$ 3、$ 4、$ 5];次へ}!(($ 2、$ 3、$ 4)file1){print XX} 'file1 file2。 XXは何ができますか? ($ 2、$ 3、$ 4)のfile1をgrepするだけで、それがfile2に存在しないことがわかったら、そのトリックを行います。 – trid3

1

あなたはfile1に一致しない行を見つけることができます。

$ grep -v -F -f <(awk '{ print $3,$4,$5 }' file2) file1 
2016-01-06T05:38:31 2016-01-06T05:23:33 2016006 120E A TM Current 
2016-01-06T07:34:01 2016-01-06T07:01:51 2016006 090E B TM Current 
2016-01-06T07:40:44 2016-01-06T07:40:41 2016006 080E A TM Alt 
2016-01-06T08:14:45 2016-01-06T08:06:33 2016006 080E C TM Current 

ただ、このどこかにリダイレクトし、その後file1上書きします。

+0

は絶対にそれはすべての行の全体にわたるfile2の内容のためgrepingていますので、このサンプル入力与えられた期待される出力を生成する場合であっても、として、一般的に次の2つのファイルの内容に応じて、偽の一致を得るだろうことをしないでくださいfile1のターゲットフィールドではなくfile1の –

関連する問題