awk를 사용하여 중복 항목을 제거하는 것은 매우 일반적이고 간단합니다. 하지만 하나의 열만 비교할 때는 중복된 행만 인쇄해야 합니다. 나는 다음 명령을 시도했습니다.
awk 'seen[$2]++'
그러나 보시다시피 결함이 있습니다. 중복된 내용을 인쇄하지만 두 번째 발생 이후에만 인쇄됩니다. 저는 이제 막 unix와 bash에 익숙해지기 시작했는데, 해결책을 제게 설명해 주시면 감사하겠습니다.
답변1
이를 수행하는 두 가지 방법을 볼 수 있습니다.
파일을 두 번 반복합니다.
첫 번째 반복에서는 각 $2의 발생 횟수를 셉니다.
두 번째 반복에서는 개수가 1보다 큰 줄만 인쇄됩니다.awk 'NR == FNR {count[$2]++; next} count[$2] > 1' file file
데이터의 단일 반복:
$2가 나타나는 횟수를 세어야 합니다.그리고$2마다 어떤 행이 발생했는지 기억하세요.
이 답변은 GNU awk를 사용하여 배열 배열을 나타냅니다. 출력 순서는 입력 데이터와 같을 수 없습니다. 또한 전체 파일을 메모리에 저장해야 합니다.
gawk ' { lines[$2][++count[$2]] = $0 } END { for (x in lines) if (count[x] > 1) for (i=1; i<=count[x]; i++) print lines[x][i] } ' file
입력 파일을 사용하여 테스트합니다.
$ cat file
a b
b b
c b
a c
a d
b d
a e
및 예상 출력
a b
b b
c b
a d
b d
답변2
동일한 샘플 입력 사용글렌 잭맨답변
$ awk '$2 in seen{if(c[$2]--){print fl[$2]} print} !seen[$2]++{fl[$2]=$0; c[$2]=1}' file
a b
b b
c b
a d
b d
!seen[$2]++
$2
이전에 경험하지 못한 경우 :fl[$2]=$0
첫 번째 줄을 저장하세요. 입력이 정렬되지 않았고 파일의 어느 곳에나 중복이 나타날 수 있다고 가정하므로$2
임시 변수가 아닌 기반으로 저장하세요.c[$2]=1
마찬가지로 count 변수를 1로 초기화합니다.
$2 in seen
$2
이전에 이런 일이 발생한 경우 :if(c[$2]--){print fl[$2]}
이전 줄이 먼저 인쇄되고 후속 일치 조건이 실패하도록 카운터가 감소됩니다.print
그런 다음 현재 줄을 인쇄하십시오.
다른 입력으로
$ cat ip.txt
6.2 : 897 : bar
3.1 : 32 : foo
1.2 : 123 : xyz
2.3 : 32 : baz
7.5 : 897 : boo
$ awk -F: '$2 in seen{if(c[$2]--){print fl[$2]} print} !seen[$2]++{fl[$2]=$0; c[$2]=1}' ip.txt
3.1 : 32 : foo
2.3 : 32 : baz
6.2 : 897 : bar
7.5 : 897 : boo
순서는 재발이 발생하는 방식에 따라 다릅니다.
답변3
동일한 파일을 두 번 반복할 때 행 번호를 편리한 색인으로 사용할 수 있습니다. 그러면 논리가 더 명확해집니다.
awk 'NR == FNR {if ($2 in z) { y[z[$2]]; y[FNR] } z[$2]=FNR; next} (FNR in y)' file file
나는 이 질문에 답할 때 비슷한 기술을 사용했습니다.
이 트릭의 기본은 Awk가 단순히 참조로 변수를 생성하고 index in arrayname
배열 요소가 지정된 인덱스로 생성되었는지 여부에 따라 구성이 true 또는 false를 반환한다는 것입니다.