awk를 사용하여 두 파일의 두 열을 비교하고 일치하는 항목 수를 인쇄하는 방법

awk를 사용하여 두 파일의 두 열을 비교하고 일치하는 항목 수를 인쇄하는 방법

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

id  clade   mutation
243 40A titi,toto,lala
254     
267 40B lala,jiji,jojo

및 템플릿 파일 B.tsv(필드 구분 기호 = \t):

40A lala,toto,xixi,xaxa
40B xaxa,jojo,huhu
40C sasa,sisi,lala

A.tsv공통 열(클레이드)을 기반으로 템플릿의 변형을 비교하고 다음과 같이 B.tsv새 파일()의 새 열에서 발견된 일치 항목 수를 표시하고 싶습니다 .C.tsv

id  clade   mutation    number
243 40A titi,toto,lala  2
254     
267 40B lala,jiji,jojo  1

다음과 같이 두 파일을 비교하는 방법을 알고 있습니다.

awk -F"," -vOFS="," '    
    NR==FNR {
     a[$2]=$3;
     next
    }
    
    { print $0,a[$2] }
' B.tsv A.tsv > C.tsv

하지만 일치 항목을 계산하는 방법을 모르겠습니다. 좋은 아이디어가 있나요?

두 번째 질문:

.NET 파일에 얼마나 많은 돌연변이가 있는지에 대한 정보만 포함하는 새 열을 만드는 방법을 알고 싶습니다 B.tsv. total_mut다음 열의 예 C.tsv:

id  clade   mutation    number  total_mut
243 40A titi,toto,lala  2   4
254     
267 40B lala,jiji,jojo  1   3

답변1

GNU 및 awk(단어 경계 앵커) 사용:\<\>

awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{ mutations[$1] =$2; next }

{
    split($3, muts, "," );
    for(x in muts) { tmp=mutations[$2]; c+=sub( "\\<"muts[x]"\\>", "", tmp) }
}

FNR==1 { c="number" }
{ print $0, (c?c:""); c=0 }' fileB  fileA

산출:

id      clade   mutation        number
243     40A     titi,toto,lala  2
254
267     40B     lala,jiji,jojo  1

두 번째 요청에 대한 답변이 업데이트되었습니다.

awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{ mutations[$1] =$2; next }

{
    split($3, muts, "," );
    for(x in muts) { tmp=mutations[$2]; c+=sub( "\\<"muts[x]"\\>", "", tmp) }
    m=1+gsub(",", "", tmp) 
}

FNR==1 { c="number"; m="total_mut" }
{ print $0, (c?c:""), (m>1?m:""); c=m=0 }' fileB  fileA

산출:

id      clade   mutation        number  total_mut
243     40A     titi,toto,lala  2       4
254
267     40B     lala,jiji,jojo  1       3

답변2

awk 'BEGIN{ OFS=FS="\t" }
  NR==FNR{ clade[$1]=$2; next }         # save clade, mutation of B.tsv in array
  FNR==1{ print $0, "number"; next }    # print header
  !($2 in clade){ print; next }         # no match -> print record
  {                                     # else...
     split($3 "," clade[$2], tmp, ",")  # split mutations into tmp array
     for (i in tmp)                     # for all mutations
       if (++num[tmp[i]] > 1)           # if same mutation occurs more than once
         ++count                        # increment counter

     print $0, count                    # print record and count
     delete num                         # reset temporary array
     count=0                            # reset counter
  }
' B.tsv A.tsv > C.tsv

두 번째 답변:

3번째 줄을 다음으로 바꾸세요:

FNR==1{ print $0, "number", "total_mut"; next }

마지막 것을 다음 print으로 바꾸십시오.

print $0, count, split(clade[$2], tmp, ",")

답변3

접근 방식은 B 파일의 분기점 및 돌연변이로 색인화된 배열을 만드는 것입니다. 그런 다음 파일 A의 돌연변이를 반복합니다.

탭으로 구분된 파일로 작업하는 것은 약간 까다롭습니다. 특히 클레이드 없이 열 수를 유지하는 것은 더욱 그렇습니다.

A 파일에 필요한 열 번호를 cClade 및 cMut로 정의하고 전체 데이터 형식과 일치하도록 변경합니다.

후속 질문의 경우, Split()이 반환한 nMut(변이 수)를 저장하고 이를 인쇄물(제목 및 세부 정보)에 추가합니다. 이 버전도 테스트했습니다.

#! /bin/bash

Match () {  #:: (data, template)

    Awk='
BEGIN { FS = "\t"; Sep = ","; cClade = 20; cMut = 41; }
F == "B" {
    nMut[$1] = split ($2, V, Sep);
    for (j in V) Mut[$1 Sep V[j]];
    next;
}
! $2 { printf ("%s%s%s\n", $0, FS, FS); next; }
FNR == 1 { printf ("%s%s%s%s%s\n", $0, FS, "number", FS, "total_mut"); next; }
{
    n = 0;
    split ($cMut, V, Sep);
    for (j in V) if (($cClade Sep V[j]) in Mut) ++n;
    printf ("%s%s%s%s%s\n", $0, FS, n, FS, nMut[$cClade]);
}
'
    awk -f <( printf '%s' "${Awk}" ) F="B" "${2}" F="A" "${1}"
}

    Match useTemplate.A.tsv useTemplate.B.tsv > useTemplate.C.tsv

답변4

이것은 다차원 배열을 처리하기 위해 GNU awk를 사용합니다:

gawk '
    BEGIN {
        FS = "[\t,]"
        OFS = "\t"
    }
    FILENAME == ARGV[1] {
        for (i = 2; i <= NF; i++)
            B[$1][$i] = 1
        next
    }
    FNR == 1 {
        print $0, "number", "total_mut"
        next
    }
    !($2 in B) {
        print
        next
    }
    {
        count = 0
        for (i = 3; i <= NF; i++)
            if ($i in B[$2])
                count++
        print $0, count, length(B[$2])
    }
' {B,A}.tsv
id      clade   mutation        number  total_mut
243     40A     titi,toto,lala  2       4
254
267     40B     lala,jiji,jojo  1       3

관련 정보