ドメインのリストがあります。例は次のとおりです。
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.com
とmedia.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.ccc
aaa.bbb.ccc
\.bbb\.ccc$
その後、このスクリプトは2番目の呼び出しで元のデータに適用され、sed
標準入力ストリームを介して編集スクリプトを読み込みます。
初期コマンドを少し変更すると、次sed
のように削除できます。grep
sed
$ 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には、不変の「符号」や正規表現拡張機能(/x
Perlの-オプション)などの素晴らしいデフォルトがたくさんあります。カスタム文字クラスは、<+[…]>
肯定文字クラスと否定文字クラスの両方に使用できます<-[…]>
。 Rakuのキャプチャは、最初から始まる$0
Perlとは異なり、最初から始まります$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
答え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.org
fwikipedia.org
doms[]
2番目のスクリプトはawkを使用して各ドメイン名を逆順に印刷するため、として印刷し、リスト全体をこのfiles.media.wikipedia.org
リストorg.wikipedia.media.files
にリンクしてsort -u
重複エントリを削除し(オプション)、結果としてより短い(つまり親)ドメイン名がすぐに表示されます。サブドメインを前に印刷してください。次に、awk
現在のリバースドメイン名が前のドメイン名の先頭の部分文字列であることを確認します。この文字列自体はサブドメインではありません。その場合、そのドメインはサブドメインであるためスキップし、そうでない場合は、印刷して(元の順序に戻す)、比較する次のドメインの新しい基本親として覚えてください。不明な場合は、各コマンドを個別に実行して出力内容を確認してください。