サブドメインまたは既存のドメインの削除

サブドメインまたは既存のドメインの削除

ドメインのリストがあります。例は次のとおりです。

account.google.com
drive.google.com
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
files.media.wikipedia.org
bible.com

既存のドメインのサブドメインをすべて削除したいと思います。たとえば、上記のリストの場合google.commedia.wikipedia.orgサブドメインがあるため、そのサブドメインを削除する必要があります。

したがって、上記のリストの結果は次のようになります。

google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

Pythonでいくつかのコードを書いてみましたが、完了するのに時間がかかります。これを最も速くするにはどうすればよいですか?

答え1

.あなたの質問は、「追いつかない最長のaだけを維持し、行の終わりまでは何も維持しない.でください。これを一意にしてください」と再定式化できるように聞こえます。.その場合は、次のことができます。

$ awk -F"." -v OFS="." '{print $(NF-1),$(NF)}' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

または、すべてのタスクを実行するには、次の手順を実行しますawk

$ awk -F"." '{ k[$(NF-1)"."$(NF)]++}END{for (i in k){print i}}' file 
bgoogle.com
bible.com
wikipedia.org
google.com

またはGNU grep

$ grep -oP '[^.]+\.[^.]+$' file  | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

またはPerlとGNUの並べ替え

$ perl -pe 's/.*?([^.]+\.[^.]+$)/$1/' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

または単にパール

$ perl -ne '$k{$1}++ for s/.*?([^.]+\.[^.]+$)/$1/; END{ print keys(%k) }' file 
bible.com
bgoogle.com
wikipedia.org
google.com

または単にパール

$ perl -ne 's/.*?([^.]+\.[^.]+)$/$1/; next if ++$k{$1}>1; print' file 
google.com
bgoogle.com
wikipedia.org
bible.com

またはsedとソート

$ sed -E 's/.*\.([^.]+\.[^.]+)$/\1/' file | sort -u
bgoogle.com
bible.com
google.com
wikipedia.org

答え2

$ sed -e 's/\./\\./g' -e 's,.*,/\\.&$/d,' file | sed -f /dev/stdin file
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

これは、まずsed入力ファイルから編集スクリプトを生成するために使用されます。sedこのsedコマンドは最初に現在の行のすべての点をエスケープしてから、変更された行を特定の正規d表現トリガーを使用するコマンドに変換します。

質問に提供されたファイルの場合、編集スクリプトは次のようになります。

/\.account\.google\.com$/d
/\.drive\.google\.com$/d
/\.google\.com$/d
/\.bgoogle\.com$/d
/\.yahoo\.co\.uk$/d
/\.stats\.wikipedia\.org$/d
/\.media\.wikipedia\.org$/d
/\.files\.media\.wikipedia\.org$/d
/\.bible\.com$/d

.このスクリプトは、で終わるホスト名と、その後にソースデータのホスト名を含む入力行の両方を削除します。たとえば、aaa.bbb.ccc正規表現と一致するため、データからifが削除されます。bbb.cccaaa.bbb.ccc\.bbb\.ccc$

その後、このスクリプトは2番目の呼び出しで元のデータに適用され、sed標準入力ストリームを介して編集スクリプトを読み込みます。


初期コマンドを少し変更すると、次sedのように削除できます。grepsed

$ sed -e 's/\./\\./g' -e 's/.*/\\.&$/' file | grep -v -f /dev/stdin file
google.com
bgoogle.com
yahoo.co.uk
stats.wikipedia.org
media.wikipedia.org
bible.com

grepこれは読み取り用の正規表現の基本セットを生成します-f

\.account\.google\.com$
\.drive\.google\.com$
\.google\.com$
\.bgoogle\.com$
\.yahoo\.co\.uk$
\.stats\.wikipedia\.org$
\.media\.wikipedia\.org$
\.files\.media\.wikipedia\.org$
\.bible\.com$

このユーティリティは、入力から一致する行を削除するgrepために使用されます。-v

答え3

使用幸せ(以前のPerl_6)

... @ terdonによって翻訳された優れたPerlソリューション:

~$ raku -ne 'BEGIN my %k; %k{$0}++ for s/ .*? (<-[.]>+ \. <-[.]>+ $)/$0/; END .key.put for %k;'  file

#OR:

~$ raku -ne 'BEGIN my %k; s/ .*? (<-[.]>+ \. <-[.]>+ $) /$0/; next if ++%k{$0} > 1; .put;'  file

以下は、Perlプログラミング言語ファミリーであるRakuで書かれたソリューションです。 Rakuには、不変の「符号」や正規表現拡張機能(/xPerlの-オプション)などの素晴らしいデフォルトがたくさんあります。カスタム文字クラスは、<+[…]>肯定文字クラスと否定文字クラスの両方に使用できます<-[…]>。 Rakuのキャプチャは、最初から始まる$0Perlとは異なり、最初から始まります$1

入力例:

account.google.com
drive.google.com
google.com
bgoogle.com
stats.wikipedia.org
media.wikipedia.org
files.media.wikipedia.org
bible.com

出力例:

google.com
bgoogle.com
wikipedia.org
bible.com

https://raku.org

答え4

これはおそらくawkでやりたいことです:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    { doms[$0] }
    END {
        for ( dom in doms ) {
            n = gsub(/[.]/,"&",dom)
            parent = dom
            foundParent = 0
            for ( i=1; i<n; i++ ) {
                sub(/[^.]+\./,"",parent)
                if ( parent in doms ) {
                    foundParent = 1
                    break
                }
            }
            if ( !foundParent ) {
                print dom
            }
        }
    }
' "${@:--}"

$ ./tst.sh file
media.wikipedia.org
bgoogle.com
bible.com
google.com
stats.wikipedia.org

または、ファイル全体をawkのメモリに保存したくない場合:

$ cat tst.sh
#!/usr/bin/env bash

awk '
    BEGIN { FS=OFS="." }
    {
        for ( i=NF; i>=1; i-- ) {
            printf "%s%s", $i, (i>1 ? OFS : ORS)
        }
    }
' "${@:--}" |
sort -u |
awk '
    BEGIN { FS=OFS="." }
    index($0,base".") != 1 {
        base = $0
        for ( i=NF; i>=1; i-- ) {
            printf "%s%s", $i, (i>1 ? OFS : ORS)
        }
    }

'

$ ./tst.sh file
bgoogle.com
bible.com
google.com
media.wikipedia.org
stats.wikipedia.org

上記の最初のスクリプトは、すべてのフィールドを配列のメモリに読み込み、doms[]それを繰り返して "."間の先頭の文字列を 2 つだけ残った位置まで削除し(したがって とfiles.media.wikipedia.orgなる)、また親文字列がも存在することを確認します。配列がそうであれば、現在のドメインが入力にも存在する親ドメインの子であることを知っているので、印刷しません。media.wikipedia.orgfwikipedia.orgdoms[]

2番目のスクリプトはawkを使用して各ドメイン名を逆順に印刷するため、として印刷し、リスト全体をこのfiles.media.wikipedia.orgリストorg.wikipedia.media.filesにリンクしてsort -u重複エントリを削除し(オプション)、結果としてより短い(つまり親)ドメイン名がすぐに表示されます。サブドメインを前に印刷してください。次に、awk現在のリバースドメイン名が前のドメイン名の先頭の部分文字列であることを確認します。この文字列自体はサブドメインではありません。その場合、そのドメインはサブドメインであるためスキップし、そうでない場合は、印刷して(元の順序に戻す)、比較する次のドメインの新しい基本親として覚えてください。不明な場合は、各コマンドを個別に実行して出力内容を確認してください。

関連情報