Cómo limitar la salida impresa según el número de ocurrencias (AWK)

Así que estoy tratando de rastrear individuos en nuestra networking de navigation por la pornografía a través de https. El patrón es bastante fácil de ver, más de 15 visitas consecutivas para imágenes sin reference en el encabezado HTTP en nuestros loggings de Bro.

Las columnas relevantes en Bro son $ 3 = IP del host, $ 11 = referente, $ 14 = tamaño del file, y $ 27 = tipo de mime.

Por lo tanto, actualmente estoy usando …

awk -F "\t" '$11 ~ /^\-$/ && $14 > 100000 && $27 ~ /^image/' 

Lo que me gustaría hacer es saber si hay una forma, aún dentro del command de una sola línea, de ejecutar un command secundario que le indique a awk que solo imprima líneas donde la IP en $ 3 ocurre> = 15 veces.

Creo que tendré que crear un progtwig awk para hacer algo así. Espero que haya un genio aquí que pueda ayudarme a evitar eso. No me opongo a utilizar otro command de expresión regular si funciona mejor (perl, grep, egrep, agrep, bro-cut).

Actualización: la mejor manera de explicar esto sería mediante términos de Excel. ¿Tiene awk algo así como la function de contar con Excel? = countif (C1, C: C)> 15

Registro de muestra:

 1443534069 CGAdXyZgN3wVwihi6 123.456.789.012 59713 93.184.216.98 80 1 GET 40.media.tumblr.com /1fbe50fff7a17f84acdc30b03d9b6335/tumblr_nvf1dfH8oz1tco00do1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 89522 200 OK - - - (empty) - - - - - FIGAv51OT15ak4eDCl image/jpeg 1443534069 CkST1DjXDkCBDYhYa 123.456.789.012 59712 93.184.216.98 80 1 GET 40.media.tumblr.com /e8f958e0dcd3eb419035a8d3271d07e8/tumblr_npr5drTCOO1qk489oo1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 83743 200 OK - - - (empty) - - - - - FWRWZX2XgQQqfm9OMe image/jpeg 1443534069 C8GvXwqAiR84PGGkk 123.456.789.012 59714 93.184.216.98 80 1 GET 40.media.tumblr.com /0b80deef543f6da28b48db0578fb3bd4/tumblr_n0chjkQICf1qeu577o1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 70530 200 OK - - - (empty) - - - - - FOHdJ62uCU30UE9VYg image/jpeg 1443534069 CMXgz73HlqL5Z0WVR7 123.456.789.012 59715 54.230.193.223 80 1 GET 36.media.tumblr.com /547822945f762adb310bb966c1f9c886/tumblr_nv3xgebHVH1sbsr1vo1_500.jpg - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36 0 67589 200 OK - - - (empty) - - - - - FmaN4d2eimhA2CpEmd image/jpeg 

Related of "Cómo limitar la salida impresa según el número de ocurrencias (AWK)"

Este script perl almacena cada línea de logging que coincida con los criterios (una "image /",> 100000 bytes, referrer = '-') en un hash de matrices codificadas por la dirección IP. Al final del script, imprime cada línea de matriz para cada dirección IP que tenga> 14 inputs.

Utiliza mucha memory, pero no tanta memory como lo haría si almacenara cada línea de input.

Podrías condensarlo en un juego de una sola línea, pero lo estarías haciendo ilegible / no debugible sin una buena razón.

 #! /usr/bin/perl use strict; my %LOGLINES = (); while (<>) { next unless (/\bimage\//); my @F=split("\t"); next unless ($F[10] eq '-'); next unless ($F[13] > 100000); push @{ $LOGLINES{$F[2]} }, $_; }; foreach my $key (sort keys %LOGLINES) { print @{ $LOGLINES{$key} } if (scalar @{ $LOGLINES{$key} } > 14); } 

Tenga en count que las matrices perl son basadas en cero, no basadas en 1. para que los numbers de campo se compensen por -1 a partir de lo que especificó.

Aquí hay otra versión que no usa casi tanta memory porque solo almacena hasta 15 líneas por cada dirección IP que ve, luego comienza a imprimir líneas coincidentes tal como las ve. La desventaja es que la salida no está orderada por una dirección IP, sino que se resuelve fácilmente por tuberías para sort -t $'\t' -k2 .

 #! /usr/bin/perl use strict; my %LOGLINES = (); my %count = (); while (<>) { next unless (/\bimage\//); my @F=split("\t"); next unless ($F[10] eq '-'); next unless ($F[13] > 12000); $count{ $F[2] }++; if ($count{ $F[2] } == 15) { print @{ $LOGLINES{$F[2]} }; # print all the log lines we've seen so far print $_; # print the current line } elsif ($count{ $F[2] } > 15) { print $_; # print the current line } else { push @{ $LOGLINES{$F[2]} }, $_; # store the log line for later use } };