説明する:

説明する:

Bashスクリプトを使用していくつかの比較を実行する効率的な方法を見つけようとしています。私はgrepとawkを使用していますが、非常に遅く、一致を区別するための良い方法はありません。

入力ファイル 1 を検討してください。

311 2222
833 7777
Jam 33333

そしてファイル2を入力してください。

A 833 0 0 0 0 7777 0 0 0 0
B no match - 2222 833 3333
C the cow jumps over the 311 moon 2222
D illicit Jam fox 33333 
E no match - Jam 
F 7777 833

実際、file1は約100行、file2は約10,000行です。

file1の2つの文字列をfile2の各行と比較したいと思います。 2つの文字列が行のどこにでも一致する場合は、file2に行を印刷します。上記の例では、理想的には出力は次のようになります(ただし、列形式で指定されています)。

C the cow jumps over the 311 moon 2222
---<separator>---
A 833 0 0 0 0 7777 0 0 0 0
F 7777 833
---<separator>--- 
D illicit Jam fox 33333 

一致するものは間の区切り文字でグループ化されています(833 7777はfile2の2行に一致します)。すべての一致は単語の一致であることをお勧めします。

また、注:file1の各行はfile2の1つ以上の行と一致しますが、file2の各行はfile1の1行または0行と一致します。

[file2の「一致しない」行が更新されました。]

ありがとう

ベストアンサー1

以下は、論理AND演算を使用してパターンファイルの1行に2つのパターン(スペースで区切られた)の純粋なawkソリューションです。

awk 'NR==FNR{patts[$1]=$2;next}{for (i in patts) if (($0 ~ i) && ($0 ~ patts[i])) print}' patterns file

修正する:
正規表現一致ではない単語の場合は、次の選択肢を評価できます。

awk 'NR==FNR{patts[$0]="\\<" $1 "\\>.*\\<" $2 "\\>|\\<" $2 "\\>.*\\<" $1 "\\>";next} \
{for (i in patts) if ($0 ~ patts[i]) print}' patterns file1   

実際にパターンを変換して単語一致を833 7777実行し
\<833\>.*\<7777\> | \<7777\>.*\<833\>、両方のパターンの論理ANDをシミュレートします。

このソリューションはテストされており、次の記録と一致しません。G 77771 2833

アップデート2回
これにより、区切り文字列を使用して単語一致、論理AND、および一致する各グループの印刷が保証されます。

awk 'NR==FNR{patts[$0]="\\<" $1 "\\>.*\\<" $2 "\\>|\\<" $2 "\\>.*\\<" $1 "\\>";next} \
{for (i in patts) {if ($0 ~ patts[i]) !found[i]?found[i]=$0:found[i]=found[i] ORS $0}} \
END{for (k in found) {print found[k];print "-----"}}' patterns file1

#Output
A 833 0 0 0 0 7777 0 0 0 0
F 7777 833
-----
D illicit Jam fox 33333
-----                  
C the cow jumps over the 311 moon 2222
----- 

ここでオンラインテストをしてください。

PS:awkが連想配列を処理する方法のため、ENDセクションの配列の印刷に影響を与えることはできません。ある意味では「ランダム」になります。

おすすめ記事