私はドメインから成る巨大なサイズのファイル(1万エントリ)を持っています(ランダムな順序ですが、重複ドメインはなく、任意の数のサブドメインがあります)、ここに小さな例があります:
domain.com
domain.net
sub.domain.com
anotherdomain.com
a.b.c.d.e.domain.net
5.4.3.2.1.domain.org
4.3.2.1.domain.org
編集:適切なワーキングセットは http://p.ip.fi/WRD- で入手できます(Webページは低速で、wget p.ip.fi/WRD-を使用してすぐにダウンロードできます)。
すべてのサブドメインを「削除」します。つまり、他のドメインのすべてのサブドメインを削除する新しいファイルを作成します。その例では、次のようになります(ソートは気にしないでください)。
domain.com
domain.net
anotherdomain.com
4.3.2.1.domain.org
sub.domain.com
、a.b.c.d.e.domain.net
および5.4.3.2.1.domain.org
は削除され(domain.com
、domain.net
および4.3.2.1.domain.org
のサブドメインであるため)、anotherdomain.com
が保持されます、それはちょうど別のドメインだからです。
いくつかの最適化でさまざまなアプローチを試しましたが、うまくいきましたが、ファイルに1万のエントリがあるため、速度が遅すぎます(何時間も)。役立つためには、高速でなければなりません(最大1分程度)。これが私が今持っているものです:
> $TEMP_BLACKLIST
BL=`cat $BLACKLIST`
for ZONE1 in $BL; do
KEEP=1
# sed -e "1,/^$ZONE1$/d" -> optimization: print $BLACKLIST only *after* the $ZONE1 occourence
# break -> optimization: quit the loop if not present
for ZONE2 in `echo $BL | sed -e "1,/^$ZONE1$/d"`; do
if [[ $ZONE1 == *.$ZONE2 ]] ; then
KEEP=0
break
fi
done
if [ $KEEP = 1 ] ; then
echo $ZONE1 >> $TEMP_BLACKLIST
fi
done
mv $TEMP_BLACKLIST $BLACKLIST
コードはbashスクリプト内に含める必要があるため、bashだけで、最終的にはそこから呼び出される一般的な埋め込みスクリプト言語(awk、Perlなど)を呼び出します(カスタムCコードなし)。
より良いアプローチを知っていますか?
これは別のバージョンです
sed 's/^/\./' file |
rev |
LC_ALL=C sort -u |
awk 'p == "" || substr($0,1,length(p)) != p { print $0; p = $0 }' |
rev |
sed 's/^\.//'
入力
domain.com
domain.net
sub.domain.com
anotherdomain.com
a.b.c.d.e.domain.net
5.4.3.2.1.domain.org
4.3.2.1.domain.org
b.c
a-b.c
b.b.c
btcapp.api.btc.com
btc.com
出力
a-b.c
b.c
4.3.2.1.domain.org
btc.com
domain.com
anotherdomain.com
domain.net
http://p.ip.fi/WRD- の推奨データセットを試すと、収集したソースファイルには59683行が含まれ、フィルターされたリストには34824行あります。36行にgrep btc.com | wc -l
フィルター済みリストに適用されます。
これを試して、
rev file \
| sort -u \
| tr '.' ',' \
| awk '$0!~dom_regex{print;dom_regex="^"$0"[.]";};NR==1{dom_regex="^"$0"[.]";print};' \
| tr ',' '.' \
| rev
出力:
4.3.2.1.domain.org
domain.com
anotherdomain.com
domain.net
説明:
sort
逆転されたファイルと重複行を排除します。このステップでは、「1種類」のドメイン/サブドメインを、最短のものと一緒にグループ化します。awk
部分は、次のものが同じ種類であるかどうかを調べます(変数dom_regex
に正規表現として保存されています)。そうでない場合は、行を出力して新しいdom_regex
を設定します。それ以外の場合、行はスキップされます。ドメイン拡張が1つしかない場合は、これを試してください。
awk -F '.' '!seen[$(NF-1)"."$NF]++' file
domain.com
domain.net
anotherdomain.com