あるファイルの行が別のファイルのデータサブセットであることを確認する

あるファイルの行が別のファイルのデータサブセットであることを確認する

file1.txt次のデータを含むファイルがあります。

MIME_HTML_ONLY
SUSPICIOUS_RECIPS
SORTED_RECIPS
HFILTER_HELO_5

他のファイルにはfile2.txt次の行があります。

HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
SORTED_RECIPS HFILTER_HELO_5
MIME_HTML_ONLY HFILTER_FROM_BOUNCE
SUSPICIOUS_RECIPS ANY_OTHER_WORD
:
:

file2.txt行のすべての単語が現在のデータのサブセットであるデータのすべての行を検索したいと思います。file1.txt

例えば出力上記は次の行でなければなりません。 SORTED_RECIPS HFILTER_HELO_5

これで個々の行を繰り返し読み、file2.txtそれがのサブセットであることを確認できますfile1.txt。ただし、1000行の異なる行に対してこれを行う必要がありますfile1.txt's。したがって、file2.txtすべての行に対してループを繰り返すのfile1.txtは非常に遅いです。これを行うために使用できる効率的な方法はありますかawk sed grep

答え1

awk 'FNR == NR && $0 !~ /^[[:blank:]]*$/ { Dict[$0] = 1 }
     FNR != NR {
        i = 1
        while( i <= NF && Dict[ $i] == 1) i++
        if( i > NF) print
        }
    ' File1.txt File2.txt
  • 普遍的で、file2の各行のフィールド/単語数に依存しません。
  • 両方のファイルのソートされたコンテンツとソートされていないコンテンツを処理します。
  • メモリを使用した最初のファイルのロード辞書だから、多くの単語を検証したい場合は、最善ではないかもしれません。
  • awkに提供されるファイルの順序は必須です。
    • 最初は事前参照です。
    • その他(少なくとも1つ)はフィルタリングするファイルです。

コンセプト:

  • 値をインデックスとして使用して、配列内の各単語をロードします。
    • 値1を使用します(割り当てられていない場合、デフォルトは0です)。
    • 最初のファイルで[ここでFNR(ファイルレコード番号)= NR(ファイルが最初に開かれた後のレコード番号)、デフォルトではレコードはawkの1行です]
    • 空白行にフィルタがあります(文字がないか空白のみがあります)。
  • カウンタ初期化(i)
  • 各フィールド(スペース区切り文字のため、デフォルトではここにある単語)を辞書の対応するフィールドと比較します。存在する場合(値= 1)、次のフィールドにループしてカウンタ(i)をインクリメントします。
  • ループの後、カウンタ(i)がフィールド(単語)の数より大きい場合、すべての単語が一致し、その行が印刷されます。
  • 次の行項目で繰り返す

答え2

次のスクリプトfile1.txtgrep -E

#!/bin/sh
regex="^($(awk '{printf $0"|"}' $1) )+\$"
grep -E "$regex" $2

使用法:

$ ./script.sh file1.txt file2.txt 
SORTED_RECIPS HFILTER_HELO_5

$regex以下でコンパイルされましたfile1.txt

^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$

数千file1.txt、数百万行の場合は、次のスクリプトをfile2.txt使用してすべての行を単一のawkプログラムにコンパイルすることをお勧めします。file1.txt's

#!/bin/sh
for i; do
        regex="^($(awk '{printf $0"|"}' $i) )+\$"
        echo "/$regex/ { print \"$i: \"\$0 }"
done

たとえば(file1.txt's名前付きmatch1.txt match2.txt match3.txt):

$ ./script2.sh match*.txt 
/^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$/ { print "match1.txt: "$0 }
/^(HFILTER_FROM_BOUNCE|FORGED_OUTLOOK_HTML|ANY_OTHER_WORD| )+$/ { print "match2.txt: "$0 }
/^(SORTED_RECIPS|HFILTER_HELO_5|MIME_HTML_ONLY|HFILTER_FROM_BOUNCE| )+$/ { print "match3.txt: "$0 }

$ ./script2.sh match*.txt >match.awk
$ awk -f match.awk file2.txt 
match2.txt: HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
match1.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: MIME_HTML_ONLY HFILTER_FROM_BOUNCE

関連情報