중복된 행을 제거하고 [중복]을 되돌립니다.

중복된 행을 제거하고 [중복]을 되돌립니다.

글쎄, 중복된 행을 제거하고 싶지만 그보다 조금 더 복잡합니다..

users.txt라는 파일이 있는데 파일의 예는 다음과 같습니다.

 users:[email protected]
 users1:[email protected]

이제 내 시스템의 버그로 인해 사람들이 다른 사람과 동일한 이메일 주소로 등록할 수 있으므로 행에 동일한 이메일 주소가 여러 번 있는 경우 상황을 제거하고 싶습니다. 문제의 예는 다음과 같습니다.

 user:display:[email protected]
 user2:[email protected]
 user3:[email protected]
 user4:[email protected]

사용자, user2, user3, user4가 모두 동일한 이메일을 갖고 있다는 점에 주목하세요. user2, user3, user4를 삭제하고 싶지만 사용자는 유지하고 싶습니다. 또는 그 반대로(요청한 대로 첫 번째 항목 선택) 동일한 이메일이 포함된 다른 행을 삭제합니다..

그러므로 만일

 [email protected] is in 20 lines remove 19
 [email protected] is in 555 lines remove 554
 and so fourth..

답변1

여기에는 awk가 필요합니다. 확인하려는 필드는 각 행의 첫 번째 필드이므로 따옴표만 사용하세요 $1.

awk -F: '! ($1 in seen) {print; seen[$1]}' users.txt

"골프"를 통해 이를 크게 줄일 수 있습니다.

awk -F: '!a[$1]++' users.txt

더 긴 형식은 설명이 거의 필요하지 않습니다. 값을 할당하지 않고도 각 이메일 주소를 인덱스로 사용하여 연관 배열을 구축합니다. 그런 다음 이메일 주소가 이전에 "보였는지"(즉, 연관 배열에 특정 이메일 주소가 인덱스로 포함되어 있는지) 확인할 수 있고, 그렇지 않은 경우 전체 줄을 인쇄할 수 있습니다.

더 짧은 형식은 실제로 거의 동일한 작업을 수행하지만 더 짧은 코드에 대해서는 더 많은 설명이 필요합니다.

후위 ++연산자는 변수에 대해 작동합니다.뒤쪽에표현식이 평가되므로 이에 대해서는 나중에 다시 다루겠습니다.

awk에서 0은 false를 의미하고 0이 아닌 경우 true를 의미합니다. !진리값을 부정하고 뒤집는 것입니다.

중괄호 외부에 나타나면 표현식은 부울 표현식으로 해석되고, 표현식이 true이면 관련 연산(중괄호 내부)이 수행됩니다. 명시적으로 명시된 동작이 없으므로 전체 줄을 인쇄하는 기본(암시적) 동작이 사용됩니다.만약에표현식은 true(0이 아님)로 평가됩니다.

a기본적으로 이는 연관 배열의 이메일 주소(첫 번째 필드)를 가리키는 값을 인덱스로 검색하거나, 존재하지 않는 경우 0으로 초기화된 값을 생성하여 0을 false로 해석하거나 0이 아닌 것을 true로 해석합니다.뒤집다결과가 "true"이면 전체 줄이 인쇄된 다음 해당 지점에서 연관 배열에 저장된 값이 증가됩니다.

실제로 이것은 충분히 일반적인 Awk 관용구이지만 더 길고 더 명시적인 버전을 사용한다고 해서 당신을 비난하지는 않습니다. :)

답변2

  1. 사용암소 비슷한 일종의 영양 datamash그룹 입력2위필드를 선택하고 각 그룹화의 첫 번째 행만 유지합니다.

    datamash -t':' -g 2 rmdup 2 < users.txt
    
  2. 님의 의견으로는돈 크리스티주석은 sort이를 수행할 수 있지만 원하는 결과를 반환할 때 출력의 순서를 변경할 수도 있습니다.

    sort -t':' -k 2,2 -u users.txt
    

위의 코드는 다음과 같이 가정합니다.사용자.txt두 번째 필드를 기준으로 정렬한 다음 첫 번째 필드를 기준으로 정렬합니다.

관련 정보