Classifique uma lista de nomes de domínio (FQDNs) a partir do tld e do trabalho à esquerda

17

Estou tentando classificar uma lista de nomes de domínio (uma lista branca de filtros da Web) a partir do TLD e funcionando para cima. Eu estou procurando qualquer * nix ou windows ferramentas que podem fazer isso facilmente, embora um script seria muito bem também.

Então, se esta é a lista que você recebe

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

Isto é o que eu quero como saída.

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

Apenas no caso de você estar se perguntando por que, Squidguard, tem uma falha de bug / design. Se ambos www.example.com e example.com estiverem incluídos em uma lista, a entrada example.com será ignorada e você poderá visitar apenas o conteúdo de www.example.com . Eu tenho várias listas grandes que precisam de alguma limpeza porque alguém adicionou entradas sem procurar primeiro.

    
por Zoredache 28.02.2012 / 02:47

7 respostas

12

Este simples script python fará o que você quiser. Neste exemplo, nomeio o arquivo 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])

Para executar, use:

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

Note que isso parece um pouco mais feio desde que eu escrevi isso como mais ou menos uma simples linha que eu tive que usar notação de fatia de [::-1] onde valores negativos funcionam para fazer uma cópia da mesma lista na ordem inversa em vez de usar o mais declarativo reverse() que o faz no local de uma forma que quebra a composibilidade.

E aqui está uma versão um pouco mais longa, mas talvez mais legível, que usa reversed() , que retorna um iterador, daí a necessidade de também envolvê-lo em list() para consumir o iterador e produzir uma lista:

#!/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)))

Em um arquivo com 1.500 linhas classificadas aleatoriamente, leva ~ 0,02 segundos:

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

Em um arquivo com 150.000 linhas classificadas aleatoriamente, leva um pouco mais de 3 segundos:

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

Aqui está uma versão mais legível que faz o reverse() e sort() no local, mas é executado na mesma quantidade de tempo e, na verdade, ocupa um pouco mais de memória.

#!/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)

Em um arquivo com 1.500 linhas classificadas aleatoriamente, leva ~ 0,02 segundos:

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

Em um arquivo com 150.000 linhas classificadas aleatoriamente, leva um pouco mais de 3 segundos:

Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.08
Maximum resident set size (kbytes): 219152
    
por 28.02.2012 / 09:01
9

Aqui está um script do PowerShell que deve fazer o que você deseja. Basicamente, ele joga todos os TLDs em uma matriz, inverte cada TLD, ordena-os, inverte-os de volta à sua ordem original e os salva em outro arquivo.

$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

Ranqueou em 1.500 registros - levou 5 segundos em uma área de trabalho razoavelmente poderosa.

    
por 28.02.2012 / 02:48
7

cat domain.txt | rev | classificar | rev

    
por 04.02.2015 / 23:26
6

Em scripts Unix: reverse, sort and reverse:

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}'
    
por 29.02.2012 / 19:02
5

Ligeiramente menos enigmático, ou pelo menos mais bonito, Perl:

use warnings;
use strict;

my @lines = <>;
chomp @lines;

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

print "$_\n" for @lines;

Este é um exemplo simples de uma transformação de Guttman-Rosler : convertemos as linhas na forma ordenável apropriada ( aqui, divida o nome do domínio em períodos e inverta a ordem das partes), classifique-as usando a classificação lexicográfica nativa e converta as linhas de volta para sua forma original.

    
por 28.02.2012 / 16:36
3

Aqui está em (curto e enigmático) perl:

#!/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" }
    
por 28.02.2012 / 05:44
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}'

O que isto faz é inverter cada campo no nome do domínio, ordenar e reverter de volta.

Isso realmente classifica a lista de domínios, lexicograficamente baseada em cada parte do nome de domínio, da direita para a esquerda.

A solução reversa ( rev <<<filename>>> | sort | rev ), não, eu tentei.

    
por 18.07.2017 / 17:30