awk를 사용하여 중복 항목만 작성

awk를 사용하여 중복 항목만 작성

awk를 사용하여 중복 항목을 제거하는 것은 매우 일반적이고 간단합니다. 하지만 하나의 열만 비교할 때는 중복된 행만 인쇄해야 합니다. 나는 다음 명령을 시도했습니다.

awk 'seen[$2]++'

그러나 보시다시피 결함이 있습니다. 중복된 내용을 인쇄하지만 두 번째 발생 이후에만 인쇄됩니다. 저는 이제 막 unix와 bash에 익숙해지기 시작했는데, 해결책을 제게 설명해 주시면 감사하겠습니다.

답변1

이를 수행하는 두 가지 방법을 볼 수 있습니다.

  1. 파일을 두 번 반복합니다.

    첫 번째 반복에서는 각 $2의 발생 횟수를 셉니다.
    두 번째 반복에서는 개수가 1보다 큰 줄만 인쇄됩니다.

    awk 'NR == FNR {count[$2]++; next} count[$2] > 1' file file
    
  2. 데이터의 단일 반복:

    $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를 반환한다는 것입니다.

관련 정보