다음 형식의 10-100k 줄의 다양한 텍스트 파일이 있습니다.
"2018-12-07 23:21:32",XX,99,ZZZ,250,REMOVED
"2018-12-07 23:25:17",XX,99,ZZZ,250,AVAILBLE
"2018-12-07 23:29:05",DD,11,AAA,250,REMOVED
"2018-12-07 23:30:00",CH,00,UUU,250,REMOVED
"2018-12-07 23:31:45",MM,33,OOO,250,REMOVED
"2018-12-07 23:46:41",XX,99,ZZZ,250,REMOVED
위의 예에서는 열 2, 3, 4가 동일한 3개의 레코드(XX,99,ZZZ - 행 1/2/6)가 있음을 알 수 있습니다. 처음 두 행을 삭제하고 마지막 행만 유지해야 합니다.
원하는 출력은 아래와 같습니다.
"2018-12-07 23:29:05",DD,11,AAA,250,REMOVED
"2018-12-07 23:30:00",CH,00,UUU,250,REMOVED
"2018-12-07 23:31:45",MM,33,OOO,250,REMOVED
"2018-12-07 23:46:41",XX,99,ZZZ,250,REMOVED
매우 느리고 100k~라인의 파일에 대해 메모리 오류를 발생시키는 PHP 스크립트가 있습니다.
답변1
마지막 항목만 남기고 모두 삭제하는 것보다 일련의 중복 항목 중 첫 번째 항목만 남기고 모두 삭제하는 것이 더 쉽습니다. 다음과 같이 시도해 볼 수 있습니다.
$ tac file | awk -F, '!seen[$2 FS $3 FS $4]++' | tac
"2018-12-07 23:29:05",DD,11,AAA,250,REMOVED
"2018-12-07 23:30:00",CH,00,UUU,250,REMOVED
"2018-12-07 23:31:45",MM,33,OOO,250,REMOVED
"2018-12-07 23:46:41",XX,99,ZZZ,250,REMOVED
답변2
BEGIN { FS = "," }
FNR == NR {
if (seen[$2,$3,$4])
delete lines[seen[$2,$3,$4]]
lines[FNR]
seen[$2,$3,$4] = FNR
next
}
FNR in lines
프로그램은 awk
동일한 파일을 두 번 읽을 것으로 예상합니다. 파일을 처음 읽을 때 FNR == NR
블록만 실행됩니다. lines
배열의 키로 출력할 줄 번호를 기억합니다 . 두 번째, 세 번째, 네 번째 열의 특정 조합이 있는 행이 이미 표시된 경우 가장 가까운 행 번호를 키로 삽입하고 이전(문 delete
.
파일의 두 번째 구문 분석 중에 발생하는 모든 일은 배열에서 현재 줄 번호를 조회하는 것입니다 lines
. 발견되면 해당 행을 인쇄하십시오.
동일한 코드의 "한 줄" 버전을 실행하는 예:
$ awk -F, 'FNR==NR { if(s[$2,$3,$4]) delete l[s[$2,$3,$4]]; l[FNR]; s[$2,$3,$4]=FNR; next}; FNR in l' file file
"2018-12-07 23:29:05",DD,11,AAA,250,REMOVED
"2018-12-07 23:30:00",CH,00,UUU,250,REMOVED
"2018-12-07 23:31:45",MM,33,OOO,250,REMOVED
"2018-12-07 23:46:41",XX,99,ZZZ,250,REMOVED