로그 파일에서 가장 많이 나타나는 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
예약되어 있음 을 알 수 있습니다 .$1
AWK END 동작이 매뉴얼 페이지의 $0에 마지막 줄을 로드하는지 여부.)
awk
연관 배열을 사용하십시오. 이는 모든 문자열을 인덱스로 사용할 수 있음을 의미합니다. 숫자 배열이 작동하는 이유는 배열의 첨자가 a[1]
단일 문자인 문자열이기 때문입니다. 그것은 동등할 수도 있고 짝수일 수도 있습니다. IP 주소의 점선 사각형은 단순한 문자열입니다.a[]
1
a[one]
a[banana]