여러 파일의 특정 열을 결합하는 방법

여러 파일의 특정 열을 결합하는 방법

데이터 파일이 있습니다 A.tsv(필드 구분 기호 = \t).

id  clade   mutation
243 40A SDF
254 20B
261 40A
267 20B

B.tsv(필드 구분 기호 = \t):

id  clade   mutation
243 40A
254 20B
261 40A
267 20B SLT

C.tsv(필드 구분 기호 = \t):

id  clade   mutation
243 40A
254 20B
261 40A MGG
267 20B

모든 파일 간에 다른 유일한 열은 열이라는 것을 알고 모든 파일을 하나로 연결하고 싶습니다 mutation. 예상되는 결과는 다음과 같습니다.

id  clade   mutation
243 40A SDF
254 20B
261 40A MGG
267 20B SLT

지금까지 나는 다음을 시도했습니다.

awk 'BEGIN{FS=OFS="\t"} NR==FNR{klos[NR]=$3; next} $3==""{$3=klos[FNR]} 1' *.tsv > output.tsv

하지만 작동하지 않습니다. 할 수 있는 방법이 있나요? 감사해요

추신: 이것은 샘플 테스트입니다. 실제 경우에는 3개 이상의 파일이 있습니다. 하지만 예제와 마찬가지로 mutation해당 열에 동일한 내용을 가진 두 개의 파일이 없습니다.

답변1

모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.

$ cat tst.awk
BEGIN { FS=OFS="\t" }
(NR == FNR) || ($3 != "") {
    fnr2rec[FNR] = $0
}
FILENAME == ARGV[ARGC-1] {
    print fnr2rec[FNR]
}

$ awk -f tst.awk A.tsv B.tsv C.tsv
id      clade   mutation
243     40A     SDF
254     20B
261     40A     MGG
267     20B     SLT

답변2

그런 다음 다음을 사용하여 paste출력을 처리합니다 awk.

paste file[ABC].tsv |\
awk 'BEGIN{ FS=OFS="\t" } { for(i=3; i<=NF; i+=3) if($i"")break; print $1, $2, $i }'

사용되는 조건은 if($i"")breaknull이 아닌 첫 번째 필드가 발견되면 for 루프를 중단한 다음(awk가 문자열 비교를 수행하도록 하려면 큰따옴표를 사용함) 필드 #1, #2 및 이전에 발견된 null이 아닌 필드만 인쇄하는 것입니다. 필드 #i Pass에 있습니다.

답변3

이것은 효과가 있을 것입니다(반대의 결과가 마음에 들지 않는다면).

[root@SE ~]# awk 'BEGIN{FS=OFS="\t"} { if($3>0) { print }}' A.tsv B.tsv C.tsv | sort -ru

나는 에 익숙하지 않기 때문에 아마도 이것을 달성하는 더 쉬운 방법이 있을 것이라고 확신합니다 awk.

내가 한 일은 3개의 파일을 모두 인쇄하고 변형에서 문자가 없는 모든 줄을 제거하는 것뿐이었습니다. 그런 다음 파이프라인은 sort -u모든 중복 항목을 제거합니다. 이 -r플래그는 순서를 반대로 합니다.

[root@SE ~]# awk 'BEGIN{FS=OFS="\t"} { if($3>0) { print }}' A.tsv B.tsv C.tsv | sort -ru
id  clade   mutation
267 20B SLT
261 40A MGG
254 20B SLT
243 40A SDF

@Quasimodo는 이것을 단순화했습니다. 감사해요.

awk 'BEGIN{FS=OFS="\t"} (FNR>1 || NR==1) && $3' A.tsv B.tsv C.tsv

처리된 첫 번째 줄(즉, 첫 번째 입력 파일의 헤더)이거나 처리된 모든 줄인 경우 한 줄을 인쇄합니다.아니요헤더이지만 비어 있지 않은 세 번째 필드가 포함되어 있습니다. { ... }규칙 블록( ) 외부의 부울 표현식이 "true"로 평가되어 awk현재 행이 인쇄되어야 함 을 나타내기 때문에 작동합니다 .

답변4

Bash 명령줄 유틸리티를 사용하는 한 가지 방법은 다음과 같습니다.

## initialization 
ref= tmpdir=$(mktemp -d) cn=3

for f in ./*.tsv;do
  : ${ref:="$f"}
 < "$f" cut -f"$cn" > "$tmpdir/$f"
done

paste <(cut -f-"$((cn-1))" "$ref") "$tmpdir"/* |
tr -s '\t' |
sed -ne "1s/\t/\n/$cn" -e 's/\t*$//;P'

결과:

id  clade   mutation
243 40A SDF
254 20B
261 40A MGG
267 20B SLT

관련 정보