날짜/시간을 기준으로 로그 파일의 마지막에 나타나는 고유한 줄만 인쇄합니다.

날짜/시간을 기준으로 로그 파일의 마지막에 나타나는 고유한 줄만 인쇄합니다.

저는 다음 형식의 로그 파일로 작업하고 있습니다.

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 

관련 정보