Сортуйте список доменних імен (FQDN), починаючи з tld та ліворуч


20

Я хочу сортувати список доменних імен (список білого списку веб-фільтрів), починаючи з TLD і працюючи вгору. Я шукаю будь-які * nix або windows інструменти, які можуть це легко зробити, хоча сценарій теж буде добре.

Тож якщо це список, який вам надано

www.activityvillage.co.uk 
ajax.googleapis.com 
akhet.co.uk 
alchemy.l8r.pl 
au.af.mil 
bbc.co.uk 
bensguide.gpo.gov 
chrome.angrybirds.com 
cms.hss.gov 
crl.godaddy.com 
digitalhistory.uh.edu 
digital.library.okstate.edu 
digital.olivesoftware.com

Це те, що я хочу як результат.

chrome.angrybirds.com 
crl.godaddy.com 
ajax.googleapis.com 
digital.olivesoftware.com 
digital.library.okstate.edu 
digitalhistory.uh.edu 
bensguide.gpo.gov 
cms.hss.gov 
au.af.mil 
alchemy.l8r.pl 
www.activityvillage.co.uk 
akhet.co.uk 
bbc.co.uk

Про всяк випадок, коли вам цікаво, чому у Squidguard є помилка / помилка дизайну. Якщо обидва www.example.comі example.comобидва включені до списку, то example.comзапис ігнорується, і ви можете відвідувати лише вміст із www.example.com. У мене є кілька великих списків, які потребують певного очищення, оскільки хтось додав записи, не дивлячись спочатку.


Чи не повинні comдомени відображатися раніше eduу вашому відсортованому списку?
Свен

9
Так, я не вдається вручну сортувати, саме тому я шукаю інструмент. :)
Зоредаче


3
Також версія python там приємна порівняно з версією perl, оскільки сорти пітонів працюють у списках списків; сорт perl не має і його потрібно було реалізувати.
Марк Вагнер

1
Зі сторони, це було б набагато складніше, якби ОП попросило, щоб топ-домени відповідно до загального списку суфіксів ( publicsuffix.org ) Mozilla оброблялися як один блок. Я можу в якийсь момент прийти, щоб це зробити (було б приємно мати проект), хтось ще зацікавився?
phk

Відповіді:


15

Цей простий скрипт python буде робити те, що ви хочете. У цьому прикладі я називаю файл domain-sort.py:

#!/usr/bin/env python
from fileinput import input
for y in sorted([x.strip().split('.')[::-1] for x in input()]): print '.'.join(y[::-1])

Для його запуску використовуйте:

cat file.txt | ./domain-sort.py

Зауважте, що це виглядає трохи погірше, оскільки я написав це як більш-менш простий однолінійний текст, мені довелося використовувати позначення фрагмента,[::-1] де працюють негативні значення, щоб зробити копію того ж списку в зворотному порядку, а не використовувати більш декларативний, reverse()який робить це на місці таким чином, що порушує складність.

Ось дещо довша, але, можливо, більш читаема версія, яка використовує, reversed()що повертає ітератор, отже, потрібно також перетворити його, list()щоб споживати ітератор та створити список:

#!/usr/bin/env python
from fileinput import input
for y in sorted([list(reversed(x.strip().split('.'))) for x in input()]): print '.'.join(list(reversed(y)))

Для файлу з 1500 випадковим чином відсортованих рядків потрібно ~ 0,02 секунди:

Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.02
Maximum resident set size (kbytes): 21632

У файлі зі 150 000 випадково відсортованими рядками потрібно трохи більше 3 секунд:

Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.20
Maximum resident set size (kbytes): 180128

Ось, напевно, більш читабельна версія, яка працює reverse()і sort()на місці, але вона працює за той же час, і фактично займає трохи більше пам’яті.

#!/usr/bin/env python
from fileinput import input

data = []
for x in input():
   d = x.strip().split('.')
   d.reverse()
   data.append(d)
data.sort()
for y in data:
   y.reverse()
   print '.'.join(y)

Для файлу з 1500 випадковим чином відсортованих рядків потрібно ~ 0,02 секунди:

Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.02
Maximum resident set size (kbytes): 22096

У файлі зі 150 000 випадково відсортованими рядками потрібно трохи більше 3 секунд:

Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.08
Maximum resident set size (kbytes): 219152

Мені сподобалося бачити багато рішень. Я приймаю відповідь на основі python здебільшого тому, що саме це я використовую для багатьох моїх інших сценаріїв. Усі інші відповіді, здається, також працюють.
Зоредаче

1
Якщо хтось зацікавлений спочатку сортувати за доменним іменем, ігноруючи TLD, використовуйтеdata.sort(key=lambda x: x[1:])
Calimo

9

Ось сценарій PowerShell, який повинен робити те, що ви хочете. В основному він кидає всі TLD в масив, перевертає кожен TLD, сортує його, повертає його до початкового порядку, а потім зберігає в інший файл.

$TLDs = Get-Content .\TLDsToSort-In.txt
$TLDStrings = @();

foreach ($TLD in $TLDs){
    $split = $TLD.split(".")
    [array]::Reverse($split)
    $TLDStrings += ,$split
}

$TLDStrings = $TLDStrings|Sort-Object

foreach ($TLD in $TLDStrings){[array]::Reverse($TLD)}

$TLDStrings | %{[string]::join('.', $_)} | Out-File .\TLDsToSort-Out.txt

Розмістив його на 1500 записів - на досить потужному робочому столі знадобилося 5 секунд.


Перетворити цей скрипт у bash чи іншу мову, я думаю, слід досить просто.
Марк Хендерсон

5 секунд здається довгим лише за 1500 рядків. Моя реалізація пітона робить 1500 за частку секунди, а 150 000 - лише за 3 секунди. Як ви вважаєте, що це робить так повільно в PowerShell?
aculich

Так, це вже давно. Я навіть не знаю, чому це займає так довго. Можливо, тому, що повноваження насправді не спрямовані на подібні дії.
Марк Хендерсон

7

cat domain.txt | rev | сортувати | об


Я думаю, це спрацювало б. Мені подобається, щоб TLD був відсортований, і цього не досягти. Використовуючи це, TLD в моєму прикладі буде в порядку (uk, mil, pl, com, edu, gov), оскільки це просте право на лівий сорт, а не межі домену.
Зоредаче

найкраща відповідь, яку я бачив!
Даніель

1
rev domain.txt|sort|rev
Багатий

6

Трохи менш вибагливий, або, принаймні, гарніший, Perl:

use warnings;
use strict;

my @lines = <>;
chomp @lines;

@lines =
    map { join ".", reverse split /\./ }
    sort
    map { join ".", reverse split /\./ }
    @lines;

print "$_\n" for @lines;

Це простий приклад перетворення Гутмана-Рослера : ми перетворюємо рядки у відповідну сортувальну форму (тут, розділяємо доменне ім’я на періоди та змінюємо порядок частин), сортуємо їх за допомогою нативного лексикографічного сортування та потім конвертуємо лінії повертаються до початкової форми.


6

У сценаріях Unix: зворотний, сортування та зворотний:

awk -F "." '{for(i=NF; i > 1; i--) printf "%s.", $i; print $1}' file |
  sort |
  awk -F "." '{for(i=NF; i > 1; i--) printf "%s.", $i; print $1}'

Аналогічна річ з однією петлею: awk -F. '{for(i=NF;i>0;i--){printf ".%s",$i};printf "\t%s\n",$0}' file|sort|cut -f2Можливо, спершу потрібно викреслити місцевих господарівgrep \. file | awk ...
Річ

3

Ось це в (короткий і виразний) перл:

#!/usr/bin/perl -w
@d = <>; chomp @d;
for (@d) { $rd{$_} = [ reverse split /\./ ] }
for $d (sort { for $i (0..$#{$rd{$a}}) {
        $i > $#{$rd{$b}} and return 1;
        $rd{$a}[$i] cmp $rd{$b}[$i] or next;
        return $rd{$a}[$i] cmp $rd{$b}[$i];
} } @d) { print "$d\n" }

У вас є інформація про терміни для такого роду? Мені цікаво побачити, як це порівнюється з реалізацією PowerShell @ Mark-Henderson , а також моєю реалізацією Python . Я використовував /usr/bin/time -vдля минулого часу та максимальної статистики пам'яті.
aculich

4
Perl повністю виграє при затуханні.
Массімо

4
Охарактеризувати сценарій Perl як "короткий і виразний" зайве.
Белмін Фернандес

@aculich, за винятком сценарію повноважень, всі параметри в моєму файлі, здається, займають менше 0,1 секунди.
Зоредаче

0
awk -F"." 's="";{for(i=NF;i>0;i--) {if (i<NF) s=s "." $i; else s=$i}; print s}' <<<filename>>> | sort | awk -F"." 's="";{for(i=NF;i>0;i--) {if (i<NF) s=s "." $i; else s=$i}; print s}'

Це означає, щоб повернути кожне подане в доменному імені, сортувати та повернути назад.

Це справді сортує список доменів, лексикографічно на основі кожної частини доменного імені, справа наліво.

Зворотне рішення ( rev <<<filename>>> | sort | rev), ні, я спробував це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.