데이터 파일이 있습니다 A.tsv
(필드 구분 기호 = \t
).
id clade mutation
243 40A siti,toto,mumu
254
267 40B lala,sisi,sojo
및 템플릿 파일 B.tsv
(필드 구분 기호 = \t
):
40A toto,xixi,saxa
40B lala,sojo,huhu
40C sasa,sisi,lala
공통 clade를 기반으로 A.tsv
템플릿의 돌연변이를 비교하고 싶습니다 B.tsv
. 두 가지 질문이 있습니다.
B.tsv
"missing_mutation"이라는 새 열에 존재하지 않는 돌연변이의 이름을 어떻게 표시할 수 있습니까A.tsv
?A.tsv
에 존재하지만 (문자로 시작s
, 대소문자를 구분하지 않음) 에는 존재하지 않는 돌연변이의 이름을 "remaining_mutation"이라는 새 열에 어떻게 표시할 수 있습니까B.tsv
?
C.tsv
다음과 같습니다.
id clade mutation missing_mutation remaining_mutation
243 40A siti,toto,mumu xixi,saxa siti
254
267 40B lala,sisi,sojo huhu sisi
다음과 같이 두 파일을 비교하는 방법을 알고 있습니다.
awk -F"," -vOFS="," '
NR==FNR {
a[$2]=$3;
next
}
{ print $0,a[$2] }
' B.tsv A.tsv > C.tsv
하지만 일치하지 않는 항목을 인쇄하는 방법을 모르겠습니다. 좋은 아이디어가 있나요?
답변1
다음 awk
프로그램은 편의를 위해 awk
("진정한 이중 인덱스 배열"의 형태로) GNU를 사용하며 이 문제를 해결해야 합니다. 이는 두 파일을 인수로 사용하여 순차적으로 호출되도록 의도되었습니다 B.txt
A.txt
(코드 예제에서 수행하는 것과 마찬가지로).
#!/bin/awk -f
BEGIN{FS=OFS="\t"}
NR==FNR {
n_tmp[$1]=split($2,buff,/,/)
for (i=1;i<=n_tmp[$1];i++) mut_tmp[$1][i]=buff[i]
next
}
FNR==1 {
print $0,"missing_mutation","remaining_mutation"
}
FNR>1 {
n_curr=split($3,mutations,/,/)
mut_miss=0
mut_rem=0
# Find missing
for (j=1;j<=n_tmp[$2];j++)
{
for (i=1;i<=n_curr;i++)
{
if (mutations[i]==mut_tmp[$2][j]) break
}
if (i>n_curr) mut_miss=mut_miss ? mut_miss "," mut_tmp[$2][j] : mut_tmp[$2][j]
}
# Find remaining
for (i=1;i<=n_curr;i++)
{
for (j=1;j<=n_tmp[$2];j++)
{
if (mutations[i]==mut_tmp[$2][j]) break;
}
if (j>n_tmp[$2] && mutations[i]~/^[Ss]/) mut_rem=mut_rem ? mut_rem "," mutations[i] : mutations[i]
}
if (!mut_miss) mut_miss=""
if (!mut_rem) mut_rem=""
print $0,mut_miss,mut_rem
}
- 그러면 먼저 clade nr에 대한 상관 테이블이 생성됩니다. 템플릿을 구문 분석할 때 이를 돌연변이 목록과 비교하세요
B.tsv
. 여기서 템플릿 돌연변이 목록은 명시적으로 개별 돌연변이 배열로 분할됩니다. 편의상mut_tmp
첫 번째 인덱스가 분기 번호인 "이중 인덱스" 배열을 사용하고 있다는 점에 유의하세요 . 두 번째는 돌연변이의 색인 번호입니다. 돌연변이 개수도 배열에 저장됩니다n_tmp
. - 구문 분석할 때
A.tsv
새 헤더를 먼저 인쇄합니다. - 그런 다음 각 행에 대해 먼저 필드 3의 변형 목록을 배열로 분할합니다
mutations
. - 그런 다음 현재 클레이드( )에 대한 템플릿 돌연변이 목록의 각 항목을
mut_tmp[$2]
기존 돌연변이( )와mutations
비교하여 "누락된 돌연변이" 필드를 채웁니다. s
다음으로, 현재 변이 목록의 각 항목을 현재 클레이드의 템플릿 변이와 비교하여 "나머지 변이" 필드를 채우고 변이가 또는 로 시작하는지 확인합니다S
.
GNU를 사용할 수 없다면 다음을 대체하여 awk
대부분의 다른 구현과 함께 작동하도록 할 수 있습니다.awk
mut_tmp[a][b]
그리고
mut_tmp[a,b]
\034
이는 계통 번호와 돌연변이 이름 에 기본적으로 개별 구성 요소를 단일 문자열 배열 인덱스에 연결하는 데 사용되는 특수 문자가 포함되어 있지 않은 것으로 나타나기 때문에 작동합니다 ( SUBSEP
자세한 내용은 내부 변수를 찾으세요).
입력 예제의 출력은 다음과 같습니다.
~$ awk -f compare.awk B.tsv A.tsv
id clade mutation missing_mutation remaining_mutation
243 40A siti,toto,mumu xixi,saxa siti
254
267 40B lala,sisi,sojo huhu sisi
예제에서 요구하는 출력이 요구 사항 설명과 일치하지 않습니다.
편집하다
A.tsv
실제로 분기군은 22열에 있고 돌연변이는 41열에 있다는 점을 귀하의 의견에서 지적하셨으므로 변경하시기 바랍니다.
split($3,mutations,/,/)
도착하다split($41,mutations,/,/)
- 모든
n_tmp[$2]
발생n_tmp[$22]
mut_tmp[$2][j]
(또는[$2,j]
)에서mut_tmp[$22][j]
(또는[$22,j]
) 까지의 모든 항목
답변2
선택하다 awk
:
awk 'BEGIN{ FS=OFS="\t" }
NR==FNR{ mutations[$1] =$2; next }
FNR>1 {
split($3, muts, "," );
for(x in muts) {
if (gsub( ",?"muts[x]",?", "", mutations[$2])>0) delete muts[x] }
}
FNR==1 { $4="missing_mutation"; $5="remaining_mutation" }
{ printf ("%s", $0 OFS mutations[$2] OFS );
for(r in muts) {
if(muts[r] ~/^[Ss]/) printf("%s", sep muts[r]); sep="," }
print ""; sep=""
}' fileB fileA