2016-11-04 2 views
0

Ich habe eine Datei, die eine CIDR-Adresse und Port auf jeder Zeile enthält:Verwendung awk, CIDR Gruppe mit Ports und zählt alle Ports mit jeweiligen CIDR

192.168.1.0/24 3306 
192.168.1.0/24 55982 
10.10.10.0/24 5800 
10.10.10.0/24 39690 
10.10.10.0/24 50112 
192.168.1.0/24 3308 
192.168.1.0/24 3312 
192.168.1.0/24 3316 

Verwenden GNU Awk 4.1.4 (auf einem Linux-System), war die erste Idee, alle Ports auf einer Linie von CIDR Adresse gruppiert zu setzen, so dass dies tat es:

awk '{a[$1]=a[$1] ? a[$1]","$2 : $2} END {for (j in a) {print j" over ports: "a[j]}}' file 

192.168.1.0/24 over ports: 3306,3308,3312,3316,55982 
10.10.10.0/24 over ports: 5800,39690,50112 

ich auch eine Zählung, wie viele Ports gab es pro CIDR-Adresse hinzufügen wollte, dieses zu erhalten Ergebnis:

192.168.1.0/24 over 5 ports: 3306,3308,3312,3316,55982 
10.10.10.0/24 over 3 ports: 5800,39690,50112 

Ich habe versucht, Werte in Arrays setzen und den Schlüssel Druck, aber die Zählung kommt immer darauf 2.

awk '{a[$1]=a[$1] ? a[$1]","$2 : $2} {h[$1]++;} END {for (i in h) for (j in a) {print j" over "h[i]" ports: "a[j]}}' file 

192.168.1.0/24 over 2 ports: 3306,3308,3312,3316,55982 
10.10.10.0/24 over 2 ports: 5800,39690,50112 

Ich bin bereit, andere Dinge neben awk zu tun, aber es ist vorzuziehen, aufgrund der Dateien mit den CIDR/Ports sind Millionen von Zeilen, und awk ist schnell. Irgendwelche Ideen?

Antwort

2

ohne Multi-dim Arrays

$ awk '{a[$1]=a[$1]?a[$1] "," $2:$2; c[$1]++} 
    END{for(k in a) print k,"over " c[k] " ports:",a[k]}' file 

10.10.10.0/24 over 3 ports: 5800,39690,50112 
192.168.1.0/24 over 5 ports: 3306,55982,3308,3312,3316 
+0

Diese sehr schnell funktioniert für Dateien unter 25 MB. Wenn die Dateien größer werden, wird es langsam. Wenn ich andreatsh antworte, funktioniert es besser für größere Dateien, macht aber bei kleineren Dateien keinen großen Unterschied. – RG1

2

Dies ist meine Lösung mit awk:

awk '{ z[$1][++count[$1]]; s[$2]=$1; } 
     END { 
     for (i in z) 
     { 
      printf(i" over "count[i]" ports: "); 
      c=0; 
      # print ports according to the key value 
      # and the requested format, i.e. port1,port2,... 
      for (j in s) 
      if(s[j]==i) 
       # we don't want a comma at the end of the line, 
       # after the last port we put a newline 
       if (c<count[i]-1) 
       { 
        printf(j","); 
        c++; 
       } 
       else printf(j"\n") 
     } 
     } 
}' file 

und seine Ausgabe:

10.10.10.0/24 over 3 ports: 5800,39690,50112 
192.168.1.0/24 over 5 ports: 3306,3308,3312,3316,55982 
1
$ awk '{cnts[$1]++; ports[$1]=($1 in ports ? ports[$1] "," : "") $2} 
     END{for (ip in ports) print ip, "over", cnts[ip], "ports:", ports[ip]}' file 
10.10.10.0/24 over 3 ports: 5800,39690,50112 
192.168.1.0/24 over 5 ports: 3306,55982,3308,3312,3316