AWK 단순 프로그램은 값의 최대 발생 횟수를 찾을 때 예상과 다르게 동작합니다.

AWK 단순 프로그램은 값의 최대 발생 횟수를 찾을 때 예상과 다르게 동작합니다.

로그 파일에서 가장 많이 나타나는 IP 주소를 찾는 간단한 awk 프로그램 ip.awk가 있습니다. IP 주소는 첫 번째 열에 있습니다.

$cat ip.awk

{ ip[$1]++ }
END {
for (i in ip)
        if ( max < ip[i] ) {
                max = ip[i]
                maxnumber = i }
print maxnumber, " has accessed ", max, " times.", " $1 is: ", $1 }

나는 이것을 access.log 파일을 구문 분석하는 데 사용합니다. 이 파일의 일부 샘플 항목은 다음과 같습니다.

173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.2.1 HTTP/1.1" 200 7404 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/themes/twentytwelve/js/navigation.js?ver=20140711 HTTP/1.1" 200 1720 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2013/11/tailshadow.png HTTP/1.1" 200 11433 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2014/05/cropped-wp3.png HTTP/1.1" 200 65326 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/?p=2407 HTTP/1.1" 200 21717 "https://www.google.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"

나는 awk 스크립트가 다음을 올바르게 제공한다고 생각합니다.

$awk -f ip.awk access.log 
68.107.81.110  has accessed  311  times.  $1 is:  70.168.57.66

내 혼란은 $1 값과 관련이 있는데, awk가 로그 파일 access.log를 통해 해당 줄의 첫 번째 열 값으로 이동함에 따라 이 값은 한 줄씩 변경되어야 한다고 이해합니다.

이는 프로그램 끝에 추가한 확인("$1 is:", $1")에서 확인됩니다. 이는 마지막 줄의 IP 주소를 반환하기 때문입니다(로그 파일에는 30000줄이 넘으므로 이를 확인하는 프로그램을 만들었습니다). 스크립트가 실제로 작동합니까?

$cat testfile.log 
1   apple
2   banana
2   banana
3
3
3
4
4
4
4
5
5   flerb
5   flerb
5   flerb
5   flerb
5   flerb , green - tea
6
7
8   grapes 0 and some more filler to make a long line
9

그런데 이렇게 하면 정답이 나오는데, 인쇄해 보면 1달러에 "9"라는 값이 나오지 않습니다. 내가 무엇을 놓치고 있나요?

$awk -f ip.awk testfile.log 
5  has accessed  6  times.  $1 is: 

또 다른 변수를 없애기 위해 ip 주소의 첫 번째 열을 새 파일에 별도로 작성하고 거기에 ip.awk를 실행했는데 예상대로 전체 로그 파일에 ip.awk를 실행할 때와 정확히 동일한 결과를 얻었습니다. 또한 점으로 구분된 십진수 IP 주소가 배열에서 어떻게 작동하는지에 대한 기본적인 내용이 누락된 것 같습니다. 또한: 1.0 2.0...을 1 2에 사용하면... 여전히 정답을 얻을 수 있지만 여전히 $1 값은 아닙니다.

답변: thecarpy가 제안한 대로 문제는 테스트 파일에 값을 입력할 때 마지막 값 다음에 Enter를 누르면 추가 줄바꿈이 추가되고 해당 줄을 구문 분석할 때 $1을 빈 문자열로 설정한다는 것입니다.

답변1

프로그램 에서 awk모든 데이터를 읽었을 때 END블록이 실행되므로 구문 분석할 입력 줄이 없습니다. (일부 구현에서는 마지막 행의 첫 번째 필드로 awk예약되어 있음 을 알 수 있습니다 .$1AWK END 동작이 매뉴얼 페이지의 $0에 마지막 줄을 로드하는지 여부.)

awk연관 배열을 사용하십시오. 이는 모든 문자열을 인덱스로 사용할 수 있음을 의미합니다. 숫자 배열이 작동하는 이유는 배열의 첨자가 a[1]단일 문자인 문자열이기 때문입니다. 그것은 동등할 수도 있고 짝수일 수도 있습니다. IP 주소의 점선 사각형은 단순한 문자열입니다.a[]1a[one]a[banana]

관련 정보