여러 줄이 포함된 두 개의 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
요청할 수 있습니다 .join
join -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
다음으로 바꾸면 다음과 같은 결과를 얻을 수 있습니다.$1
awk
../../A/folder/fname2.gz