날짜/시간을 기준으로 로그 파일의 마지막 고유 행만 인쇄합니다.

날짜/시간을 기준으로 로그 파일의 마지막 고유 행만 인쇄합니다.

다음 형식의 로그 파일을 사용하고 있습니다.

Oct 12 01:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 01:30:00 server program: 192.168.1.104 text for 1.104 
Oct 12 01:30:23 server program: 192.168.1.103 text for 1.103
Oct 12 01:32:39 server program: 192.168.1.101 text for 1.101 
Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103 
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101 

나는 이것을 달성해야합니다 :

Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101

새 출력을 파일로 보내는 방법은 무엇입니까? 나는 이것을 시도했습니다 :

awk '!_[$6]++ {a=$6} END{print a}' logfile

하지만 예상한 결과가 나오지 않습니다. awk 또는 sed를 사용하여 문자열 일치를 마지막으로 본 고유 행만 제공하거나 날짜/시간을 기반으로 하려면 어떻게 해야 합니까?

답변1

두 번째 패스(대부분 해야 함)를 수행할 계획이라면 전체 레코드 대신 줄 번호만 저장할 수도 있습니다. 논리를 더 쉽게 만듭니다.

awk 'NR == FNR {if (z[$6]) y[z[$6]]; z[$6] = FNR; next} !(FNR in y)' logfile logfile

정확성 증명:

각 행 처리가 끝나면 지금까지 처리된 각 행의 수는 다음과 같습니다.누구나z또는의 인덱스(값 아님) y(둘 다는 아님)

z각 반복이 끝나면 값으로 표시되는 행은 정확히 각 IP 주소에 대해 지금까지 표시된 최신 레코드입니다.

따라서 의 인덱스는 y정확히 우리가 원하는 선입니다.아니요인쇄.

답변2

전체 행( $6배열 인덱스로 사용됨)을 저장하고 END배열 요소를 반복합니다.

awk '{z[$6]=$0};END{for (i in z) print z[i]}' logfile

하지만 결과는 정렬되지 않습니다. 다음과 같이 할 수 있습니다.

awk '{z[$6]=NR" "$0};END{for (i in z) print z[i]}' logfile | sort -k1,1n | cut -f2-
### this space ^ is a literal TAB

그러면 줄 번호가 저장됩니다. 행 번호별로 정렬하려면 행 내용을 추가하세요.


다른 방법에는 날짜별로 정렬하는 두 번째 단계가 포함됩니다(로그이기 때문에). 그러나 입력에 중복 행(즉, 전체 행)이 포함된 경우 중복 항목이 인쇄됩니다. 예를 들면 다음과 같습니다 grep.

awk '{z[$6]=$0};END{for (var in z) print z[var]}' logfile | grep -Fxf- logfile

아니면 그냥 awk:

awk 'NR==FNR{z[$6]=$0;next}
FNR==1{for (var in z) y[z[var]]}
$0 in y' logfile logfile

답변3

같은 날의 라인만 있는 경우 다음과 같이 처리할 수 있습니다.

sort -k6 -k3r logfile | uniq -f3 | sort -k3

대기열이 하루 이상인 경우에도 이 기본 방법을 사용할 수 있지만 순서를 좀 더 영리하게 지정해야 합니다. 위 명령은 타임스탬프의 시간 부분(예: 02:28:26)을 전체 타임스탬프의 프록시로 사용하기 때문에 하루 분량의 레코드만 처리할 수 있습니다 .

답변4

파일을 한 줄씩 뒤집으면 논리가 더 간단해집니다.

$ tac logfile | awk '!seen[$6]++' | tac
Oct 12 02:28:26 server program: 192.168.1.105 text for 1.105 
Oct 12 02:30:00 server program: 192.168.1.104 text for 1.104
Oct 12 02:30:23 server program: 192.168.1.103 text for 1.103 
Oct 12 02:32:39 server program: 192.168.1.101 text for 1.101 

관련 정보