#!/usr/bin/perl use strict; use warnings; ###################################################### # Funktionen # ############## # Liste einlesen # Werte: # > Name des ersten Eintrages # > Name des zweiten Eintrages # > Name des dritten Eintrages # > Filehandle # < gelesenen Liste sub parse_liste($$$$) { my ($erst,$dann,$letzt,$fh)=@_; my @liste=(); while(my $l=<$fh>) { push(@liste,{$erst=>[$1], $dann=>[$2], $letzt=>[$3]}) if($l=~/^([^\s]+)\s+(\d+)\s+([^\s]+)$/); } return @liste; } # Einträge zusammenfassen # Werte: # > die Hashrefferenz # > Name des Wertes, dessen Ihnalt zusammengefst werden soll # < String, der die vereinte liste enthält. sub myjoin($$) { my ($ref,$name)=@_; # ich benutze hier den "Nullsring" als Trenner, # da er normalerweise niemals in einem String vorkommt return join("\000", @{$ref->{$name}}); } # Werte vergelichen (als Aufruf aus "sort" heraus) # Werte: # > erste Hashreferenz # > zweite Hashreferenz # > Name des primären Sortierwertes # > Name des sekundären Sortierwertes # > Name des terziären Sortierwertes sub vergleiche($$$$$) { my ($wa,$wb,$erst,$dann,$letzt)=@_; if( myjoin($wa,$erst) eq myjoin($wb,$erst) ) { return myjoin($wa,$letzt) cmp myjoin($wb,$letzt) if( myjoin($wa,$dann) eq myjoin($wb,$dann) ); return myjoin($wa,$dann) cmp myjoin($wb,$dann); } return myjoin($wa,$erst) cmp myjoin($wb,$erst); } # Liteneinträge zusammenfassen # Werte: # > Name des ersten Wertes der übereinstimmen muss # > Name des zweiten Wertes der übereinstimmen muss # > Name des Wertes der bei positiver Prüfung zusammengefasst wird # < zusammengefasste Liste sub komibiere($$$@) { my ($erst,$dann,$letzt,@liste)=@_; # erstmal sortieren @liste=sort{ vergleiche($a,$b,$erst,$dann,$letzt) }@liste; # ein Eintrag kommt immer in die Ausgabeliste my @liste_k=({ $erst => $liste[0]->{$erst}, $dann => $liste[0]->{$dann}, $letzt => $liste[0]->{$letzt} }); shift(@liste); # Die Eingabeliste durcharbeiten while(@liste) { my $eintrag=shift(@liste); if( myjoin($eintrag,$erst) eq myjoin($liste_k[-1],$erst) && myjoin($eintrag,$dann) eq myjoin($liste_k[-1],$dann) ) { push(@{$liste_k[-1]->{$letzt}},@{$eintrag->{$letzt}}); } else { push(@liste_k,{ $erst=>$eintrag->{$erst}, $dann=>$eintrag->{$dann}, $letzt=>$eintrag->{$letzt} }); } } return @liste_k; } # Listeneinträge ausgeben # Werte: # > Name des ersten Eintrages # > Name des zweiten Eintrages # > Name des dritten Eintrages sub my_print($$$@) { my ($erst,$dann,$letzt,@l)=@_; print '/','#'x32,"\\\n"; printf("|%10s|%10s|%10s|\n",$erst,$dann,$letzt); print '+','-'x10,'+','-'x10,'+','-'x10,"+\n"; for my $i (@l) { my $e= join(',',@{$i->{$erst}}); my $d= join(',',@{$i->{$dann}}); my $l= join(',',@{$i->{$letzt}}); printf("|%10s|%10s|%10s|\n",$e,$d,$l); } print '\\','#'x32,"/\n"; } ###################################################### # Programm # ############ my @l=parse_liste('quelle','port','ziel',*DATA); print "Rohdaten\n"; my_print('quelle','port','ziel',@l); print "\"Ports\" zusammengefasst\n"; @l=komibiere('quelle','ziel','port',@l); my_print('quelle','port','ziel',@l); print "\"Quellen\" zusammengefasst\n"; @l=komibiere('ziel','port','quelle',@l); my_print('quelle','port','ziel',@l); print "\"Ziele\" zusammengefasst\n"; @l=komibiere('quelle','port','ziel',@l); my_print('quelle','port','ziel',@l); exit(0); ###################################################### # DATAZEILEN # ############## __DATA__ A 1 b A 2 b K 24 c P 2 d B 3 b B 1 b B 22 a K 2 d P 1 a P 1 b K 1 c K 2 a K 4 a C 22 c C 4 a K 22 a B 11 c D 2 e D 1 a A 33 c W 1 q L 3 w Z 11 q W 11 q Z 1 q D 1 c P 1 c