특정 필드를 기반으로 서로 다른 두 파일에서 고유한 줄 찾기

특정 필드를 기반으로 서로 다른 두 파일에서 고유한 줄 찾기

여러 줄이 포함된 두 개의 txt 파일을 비교하고 파일 1에 고유한 줄만 포함된 세 번째 txt 파일을 만들어야 합니다. 파일 1의 예는 다음과 같습니다.

../../A/folder/fname.gz | -12.36 | A:BCD:123:A, D:DFR:241:AZ1 
../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

수천 줄에 걸쳐 계속되며 파일 2의 예는 다음과 같습니다.

../../B/folder2/fname.gz | -7.65 | C:ABC:425:A
../../B/folder2/fname3.gz | -12.31 | A:BCD:758:D

../../folder/fname2.gz예제 와 같이 첫 번째 필드를 기반으로 고유한 파일 1의 모든 행을 가져와야 합니다 . 다를 folder수 있지만 fnameX.gz고유해야 합니다. folder둘 다 및/또는 을 fname포함합니다 . 각 행의 필드 수는 다를 수 있습니다. 위 예제의 예상 출력은 다음과 같습니다.-_

../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

이를 수행하는 가장 좋은 방법은 무엇입니까?

답변1

awk -F ' *[|] *' '{ k=$1; sub(".*/", "", k) }
               !z { a[k]; next } !( k in a )' file2 z=1 file1

먼저 읽고 file2파일 이름 부분을 배열에 저장합니다. 읽을 때 file1파일 이름이 배열에 없으면 한 줄을 인쇄합니다.

답변2

우리는슈워츠 변환|각 파일의 첫 번째 필드에 있는 파일 이름에 문자가 포함되어 있지 않고 필드가 |선택적 공백(공백 및/또는 탭)으로 둘러싸여 있다고 가정하는 도우미 셸 함수입니다 .

sorter먼저 입력 데이터의 첫 번째 필드에서 파일 이름을 추출하고 데이터를 정렬하기 전에 각 행에 이 파일 이름 접두사를 추가하는 도우미 함수를 정의합니다 .

sorter () {
    awk -F '[[:blank:]]*\|[[:blank:]]*' -v OFS='|' \
        '{ key=$1; sub(".*/","",key); print key, $0 }' |
    sort
}

$0최종 출력에서 ​​첫 번째 필드의 경로 이름만 필요한 경우 $1위 코드에서 을 변경하세요. $2두 번째 필드 등만 가져오도록 변경합니다 .

join유틸리티는 입력이 조인 필드에 따라 정렬된다고 가정하기 때문에 데이터를 파일 이름별로 정렬해야 합니다 .

이 함수는 표준 입력에서 데이터를 읽고, 이를 통해 첫 번째 파일을 실행하면 결과는 다음과 같습니다.

$ sorter <file1
fname.gz|../../A/folder/fname.gz | -12.36 | A:BCD:123:A, D:DFR:241:AZ1
fname2.gz|../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

각 입력 파일에 대해 이 작업을 수행하고 첫 번째 필드 조인을 사용하면 다음을 사용하여 두 번째 파일의 어떤 줄과도 쌍을 이룰 수 없는 첫 번째 파일의 줄만 출력하도록 join요청할 수 있습니다 .joinjoin -v 1

join -t '|' -v 1 <( sorter <file1 ) <( sorter <file2 ) | cut -d '|' -f 2-

마지막으로 이 명령은 명령이 각 줄에 추가한 cut파일 이름 필드를 제거합니다.awk

질문의 데이터를 고려하면 결과는 다음과 같습니다.

../../A/folder/fname2.gz | -4.56 | B:ABC:456:C | G:RFT:265:T

코드를 $0다음으로 바꾸면 다음과 같은 결과를 얻을 수 있습니다.$1awk

../../A/folder/fname2.gz

관련 정보