Classificação e Agrupamento de Domínios e Subdomínios

2

Existe uma maneira melhor de classificar e agrupar domínios e subdomínios juntos? Por exemplo, o arquivo list contendo

morefu.sub1.foo.com
www.foo.com
bar.foo.com
sub1.foo.com 
fufu.isub1.foo.com
foofoo.bar.foo.com 
morefoo.bar.foo.com
fufu.sub1.foo.com

usando

for i in $(grep -oP '(\w+).foo.com' list | sort | uniq); do grep $i list | sort; echo; done

quase funciona:

bar.foo.com
foofoo.bar.foo.com 
lotsmorefubar.bar.foo.com
morefoo.bar.foo.com

fufu.isub1.foo.com <-- should not be here
fufu.sub1.foo.com
morefu.sub1.foo.com
sub1.foo.com 

www.foo.com

com exceção de fufu.isub1.foo.com , que deve estar em uma seção por si só. Adicionar ^ e \b à expressão grep não ajudou.

Imaginando se existe uma maneira mais precisa e eficiente de fazer isso?

    
por KM. 01.10.2016 / 19:44

2 respostas

3

Que tal

tr -d [:blank:] < hosts |                           # remove trailing whitespace
perl -lne 'print join ".", reverse(split /\./)' |   # reverse order of fields
sort |                                              # sort
awk -F. '
  !seen[$1.$2.$3]++ && NR>1 {print ""}             # insert blank line when tld,dom,sub change
  {for (i=NF;i>1;i--) printf "%s.", $i; print $1}   # print fields in original order
'

dando

bar.foo.com
foofoo.bar.foo.com
morefoo.bar.foo.com

fufu.isub1.foo.com

sub1.foo.com
fufu.sub1.foo.com
morefu.sub1.foo.com

www.foo.com

Melhor (espero) a implementação do mesmo algoritmo, usando um hash de hashes perl:

#!/usr/bin/perl

use strict;
use warnings;

my %domains = ();

while (defined($_ = <ARGV>)) {
  chomp $_ ;
  $_ =~ s/\s+//;

  my @F = reverse(split(/\./));
  my $domain = join(".", @F[0..2]);

  if ( ! exists($domains{$domain}) ) {
    $domains{$domain} = {};
  }

  $domains{$domain}{join(".", @F)}++;
}

foreach my $domain (sort keys %domains) {
  foreach my $host (sort keys %{ $domains{$domain} }) {
    print join(".", reverse(split(/\./, $host))), "\n";
  }
  print "\n"
}
    
por 01.10.2016 / 20:33
0

TXR Lisp:

[(opip (mapcar (op tok-str @1 #/[^.]+/))
       (sort @1 : reverse)
       (partition-by (ret [@1 -3..-1]))
       (mapcar (op mapcar (op cat-str @1 ".")))
       (interpose "")
       tprint)
 (get-lines)]

Executar:

$ txr domain-sort.tl < data
bar.foo.com
foofoo.bar.foo.com
morefoo.bar.foo.com

fufu.isub1.foo.com

sub1.foo.com
fufu.sub1.foo.com
morefu.sub1.foo.com

www.foo.com

Basicamente, nós tokenizamos as linhas em listas de strings como ("sub1" "foo" "com") e trabalhamos com uma lista delas. Classificamos essa lista usando o reverso de seus elementos como chave; Assim, para fins de classificação, ("sub1" "foo" "com") é tratado como se fosse ("com" "sub1" "foo") . Depois disso, é uma questão de agrupamento. Isso é facilmente alcançado usando partition-by , usando os três últimos elementos como chave de particionamento. Temos que reconstituir as cadeias juntando-as a um ponto e imprimir os grupos com linhas. O último é conseguido através da inserção de uma cadeia vazia entre os grupos e permitindo que tprint faça o seu trabalho.

    
por 02.10.2016 / 04:55