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.txt
はgrep -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