Sortieren und Gruppieren von Domänen und Subdomänen

Sortieren und Gruppieren von Domänen und Subdomänen

Gibt es eine bessere Möglichkeit, Domänen und Subdomänen zu sortieren und zu gruppieren? Beispielsweise die Datei listmit

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

mit

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

funktioniert fast:

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

mit der Ausnahme, fufu.isub1.foo.comdass es in einem eigenen Abschnitt stehen sollte. Das Hinzufügen von ^und \bzum Grep-Ausdruck hat nicht geholfen.

Sie fragen sich, ob es hierfür einen genaueren und effizienteren Weg gibt?

Antwort1

Wie wäre es mit

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
'

Geben

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

Bessere (hoffentlich) Implementierung des gleichen Algorithmus unter Verwendung einesHash von Hashesin 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"
}

Antwort2

TXRLispeln:

[(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)]

Laufen:

$ 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

Im Grunde tokenisieren wir die Zeilen in Listen von Zeichenfolgen wie ("sub1" "foo" "com")und arbeiten mit einer Liste dieser. Wir sortieren diese Liste mit der Umkehrung ihrer Elemente als Schlüssel; zum Zwecke der Sortierung ("sub1" "foo" "com")wird also so behandelt, als wäre es ("com" "sub1" "foo"). Danach geht es um die Gruppierung. Dies lässt sich leicht mit erreichen partition-by, wobei die letzten drei Elemente als Partitionierungsschlüssel verwendet werden. Wir müssen die Zeichenfolgen neu zusammensetzen, indem wir sie mit einem Punkt verbinden, und die Gruppen mit Zeilen drucken. Letzteres erreichen wir, indem wir eine leere Zeichenfolge zwischen den Gruppen einfügen und es tprintseine Arbeit machen lassen.

verwandte Informationen