Existem muitas maneiras de fazer isso. Aqui estão alguns, mas use o Perl é ordens de magnitude mais rápido. Eu incluo os outros para completar:
-
Perl e hashes, ridiculamente rápidos
perl -e 'open(A,"fileB"); while(<A>){chomp; $k{$_}++} while(<>){@a=split(/,/); print if defined $k{$a[0]}}' fileA
-
Gawk e matrizes associativas, muito mais lentas
gawk '{if(FILENAME==ARGV[1]){array[$1]=1} else{if($1 in array){print}}}' fileA fileB
-
grep
, ridiculamente lento. Você precisará modificar seu arquivo B levemente para fazer com que os padrões correspondam apenas na primeira linhased 's/\(.\)/^/' fileB > fileC grep -f fileC fileA
Eu criei alguns arquivos de teste e as soluções Perl são muito mais rápidas que o grep
:
$ head -2 fileA
GO:0032513_GO:0050129
GO:0050129_GO:0051712
$ head -2 fileB
GO:0032513_GO:0050129
GO:0050129_GO:0051712
$ wc -l fileA fileB
1500000 fileA
20000000 fileB
$ time perl -e 'open(A,"fileB"); while(<A>){chomp; $k{$_}++}
while(<>){@a=split(/,/); print if defined $k{$a[0]}}' fileA > /dev/null
real 0m41.354s
user 0m37.370s
sys 0m3.960s
$ time gawk '{if(FILENAME==ARGV[1]){array[$1]=1}
else{if($1 in array){print}}}' fileA fileB
real 2m30.963s
user 1m23.857s
sys 0m9.385s
$ time (join -t, <(sort -n fileA) <(sort -n fileB) >/dev/null)
real 8m29.532s
user 13m52.576s
sys 1m22.029s
Assim, o scriptlet Perl pode passar por um arquivo de 20 milhões de linhas, procurando por 1,5 milhão de padrões e terminar em ~ 40 segundos. Não é ruim. Os outros dois são muito mais lentos, gawk
demorou 2,5 minutos e o grep
foi executado por mais de 15. Perl vence com facilidade.