데이터 파일이 있습니다 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