[Обновлено с советами Эда Мортона - спасибо]
Допущения:
- комбинация столбцов 1 + 2 уникальна в пределах
file.txt
- Столбец 3 является уникальным в пределах
file.txt
. Начнем с нескольких примеров файлов данных:
$ cat gene.dat
chr1 196575462 rs115411599 A G . . RS=115411599;RSPOS=196575462;dbSNPBuildID=132;SSR=0;SAO=0;VP=0x050000080005040436000100;GENEINFO=KCNT2:343450;WGT=1;VC=SNV;INT;ASP;VLD;HD;KGPhase1;KGPhase3;CAF=0.9994,0.000599;COMMON=1
chr2 196575462 rs115411588 A G . . RS=115411599;RSPOS=196575462;dbSNPBuildID=132;SSR=0;SAO=0;VP=0x050000080005040436000100;GENEINFO=KCNT2:343450;WGT=1;VC=SNV;INT;ASP;VLD;HD;KGPhase1;KGPhase3;CAF=0.9994,0.000599;COMMON=1
chr3 196575462 rs115411577 A G . . RS=115411599;RSPOS=196575462;dbSNPBuildID=132;SSR=0;SAO=0;VP=0x050000080005040436000100;GENEINFO=KCNT2:343450;WGT=1;VC=SNV;INT;ASP;VLD;HD;KGPhase1;KGPhase3;CAF=0.9994,0.000599;COMMON=1
# go ahead and create a *gz file we can use with zcat:
$ gzip -c gene.dat > gene.dat.gz
$ cat file.txt
chr1:196575462 rs115411599
chr2:196500077 rs115400077
chr3:196500088 rs115400088
One awk
решение:
awk '
# for first file, use fields 1+2 and 3 as indexes for our associative arrays
FNR==NR { match1[$1,$2] ; match2[$3] ; next }
# for second file, if fields 1+2 matches an index in the match1[] array then print fields $4/$5; if we found a match then go to next line in file
( ($1,$2) in match1 ) { print $4,$5 ; next }
# for second file, if field 3 matches an index in the match2[] array then print fields $4/$5
( $3 in match2 ) { print $4,$5 }
# for our first file we will replace : with <space> ; this gives us 3 fields from first file
# for our second file we will feed the results of the zcat operation
' <(sed 's/:/ /g' file.txt) <(zcat gene.dat.gz)
И результат выполнения вышеуказанного:
A G
A большое преимущество этого подхода состоит в том, что мы сканируем каждый файл только ONCE (например, пример кода в вопросе показывает zcat dbsnp.gz
, выполняемый / сканируемый несколько раз внутри while
l oop).