Eu escreveria
awk '
# store column 2 from the first file
NR == FNR {pos[$2] = 1; next}
# from the second file, print the 3rd field if it occurred in file1
$3 in pos {print $3}
' file1 file2
Eu tenho dois arquivos:
Arquivo 1:
Chromosome Position
Chr1 5242097
Chr1 4876397
Chr1 9474943
Chr1 8494518
Chr1 39872693
Chr1 9445153
Chr1 23044399
Chr1 8018859
Chr1 9474943
Chr1 42380010
Chr1 9474943
Chr1 22677151
Chr1 23044399
Chr1 42380010
Arquivo 2:
Chr1 1 0
Chr1 2 0
Chr1 3 0
Chr1 4 0
Chr1 5 0
Chr1 6 0
Chr1 7 0
Chr1 8 0
Chr1 9 0
Chr1 10 0
Chr1 11 0
Chr1 12 0
Chr1 13 0
Chr1 14 0
Chr1 15 0
Chr1 16 0
Chr1 17 0
Chr1 18 0
Chr1 19 0
Chr1 20 0
Chr1 21 0
Chr1 22 0
Chr1 23 0
Chr1 24 0
Chr1 25 0
Chr1 26 0
Chr1 27 0
Chr1 28 0
Chr1 29 0
Chr1 30 0
Chr1 31 0
Chr1 32 0
Chr1 33 0
Chr1 34 0
Chr1 35 0
Chr1 36 0
Chr1 37 0
Chr1 38 0
Chr1 39 0
Chr1 40 0
Chr1 41 0
Chr1 42 0
Chr1 43 0
Chr1 44 0
Chr1 45 0
Chr1 46 0
Chr1 47 0
Chr1 48 0
Chr1 49 0
Chr1 50 0
O File2 é muito grande, por isso não mostro a coisa toda. Os números podem subir para mais de 6 dígitos.
Eu quero buscar a terceira coluna do arquivo2 se ela corresponder à segunda coluna do arquivo1.
Eu escrevi um programa Perl, mas é muito lento. Eu estou procurando uma maneira rápida de fazer isso. Grep também é lento.
Eu escreveria
awk '
# store column 2 from the first file
NR == FNR {pos[$2] = 1; next}
# from the second file, print the 3rd field if it occurred in file1
$3 in pos {print $3}
' file1 file2
Mantenha apenas col2 do arquivo 1
awk '{print $2}' file1 > file1_col2
Em seguida, mantenha a col3 do arquivo2:
awk '{print $3}' file2> file2_col3
Agora pesquise por ocorrências de linhas file1_col2 no arquivo2_col3:
grep -f file1_col2 file2_col3
Se lento, o C ++ deve ajudar, seriamente, pode ser usado para escrever coisas rápidas também =). Salve em file.cc e compile com g++ file.cc -O2 -o file
, execute como ./file
no diretório com o arquivo; substitua firstfilename
e o segundo nome de arquivo que você precisa antes da compilação.
Você não conseguirá bater C ++ em velocidade =)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream f1("firstfilename"), f2("secondfilename");
string s;
int i1, i2, line=0;
while (!f1.eof()) {
line++;
if (f2.eof()) {
cout << "Length different!" << "\n";
}
f1>>s>>i1;
f2>>s>>i2>>i2;
if (i1 != i2) {
cout << "Not matching line " << line << " " << i1 << "<>" << i2 << "\n";
}
}
}
Se o seu primeiro arquivo é pequeno o suficiente para caber na memória, você pode fazer isso em Perl:
perl -e 'open($f1,"file1"); while(<$f1>){chomp; $k{$_}++}
while(<>){ /(.+?\s+.+?)\s/; print if defined($k{$1})' file2
Isso deve ser razoavelmente rápido, mas ainda precisa ler todo o file2
.
Use join
, inclua sort
se seus dados não forem classificados pelo campo apropriado.
join -1 2 -2 3 -o 2.3 <(sort -k2,2 file1) <(sort -k3,3 file2)
Se sort
não for necessário:
join -1 2 -2 3 -o 2.3 file1 file2
Isso está usando utilitários GNU. Para outras variantes, eu precisaria saber qual Unix você está usando. A versão acima com sort
é mostrada com a substituição do processo Bash, que também funciona em algumas outras camadas.
Como o campo de junção também é o campo de saída, -o 2.3
pode ser simplificado para -o 0
.
Tags text-processing join