발생 횟수에 따라 인쇄를 제한하는 방법(AWK)

발생 횟수에 따라 인쇄를 제한하는 방법(AWK)

그래서 저는 https를 통해 우리 네트워크에서 포르노를 검색하는 사람들을 추적하려고 합니다. 15회 이상의 연속 이미지 클릭에 대해 Bro 로그의 HTTP 헤더에 참조 URL이 없으면 패턴을 쉽게 확인할 수 있습니다.

Bro의 관련 열은 $3 = 호스트 IP, $11 = 리퍼러, $14 = 파일 크기, $27 = MIME 유형입니다.

그래서 제가 현재 사용하고 있는...

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

내가 하고 싶은 것은 한 줄 명령으로 하위 명령을 계속 실행하면서 awk에게 $3의 IP가 15번 이상 나타나는 줄만 인쇄하도록 지시하는 방법이 있는지 아는 것입니다.

내 생각엔 비슷한 일을 하려면 awk 프로그램을 만들어야 할 것 같다. 이 문제를 피하는 데 도움을 줄 수 있는 전문가가 여기 있기를 바랍니다. 나는 다른 정규식 명령이 더 잘 작동한다면(perl, grep, egrep, agrep, bro-cut) 사용하는 것에 반대하지 않습니다.

업데이트: 이를 설명하는 가장 좋은 방법은 Excel 용어를 사용하는 것입니다. awk에는 countif Excel 함수와 유사한 기능이 있습니까? =개수(C1,C:C)>15

샘플 로그:

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

답변1

이 Perl 스크립트는 기준("image/", > 100000바이트, 참조자 = '-')과 일치하는 각 로그 행을 IP 주소로 입력된 배열 해시에 저장합니다. 스크립트 끝에서 14개 이상의 항목을 포함하는 모든 IP 주소에 대한 모든 배열 행을 인쇄합니다.

많은 메모리를 사용하지만 각 입력 행을 저장하는 만큼 많지는 않습니다.

한 줄로 압축할 수 있지만 아무 이유 없이 읽을 수 없거나 디버깅할 수 없게 됩니다.

#! /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);
}  

Perl 배열은 1 기반이 아닌 0 기반임을 참고하세요. 따라서 필드 번호는 지정한 필드 번호에서 -1만큼 오프셋됩니다.

여기 보이는 각 IP 주소에 대해 최대 15줄만 저장한 다음, 보이는 일치하는 줄을 인쇄하기 시작하기 때문에 많은 메모리를 사용하지 않는 또 다른 버전이 있습니다. 단점은 출력이 IP 주소별로 정렬되지 않지만 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
    }
};

관련 정보