Bash

使用腳本(bash、awk 或類似)修剪文件中其他域的子域

  • September 3, 2019

我有一個巨大的文件(一萬個條目),包含域(以隨機順序,但沒有重複的域和任意數量的子域),這裡有一個小例子:

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-上提供了適當的工作集(網頁速度很慢,使用 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.net5.4.3.2.1.domain.org被刪除(作為domain.com,domain.net和的子域4.3.2.1.domain.org),anotherdomain.com被保留,因為它只是一個不同的域。

我嘗試了一些優化的不同方法,它們奏效了,但是它們太慢了(很多小時),因為文件有一萬個條目。為了有用,它必須很快(最多 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

解釋:

  1. sort反轉文件並消除重複行。此步驟會將“一種”的域/子域與前面最短的一個組合在一起。
  2. awk如果下一個是同一類型(保存為變數中的正則表達式),該部分將查看dom_regex。如果沒有,它將列印該行並設置 new dom_regex。否則,將跳過該行。
  3. 再次反轉文件。

引用自:https://unix.stackexchange.com/questions/538810