Comparar colunas de dois arquivos

1. Comparar colunas de dois arquivos

Giordano Bruno Soares Souza
jwojwo

(usa CentOS)

Enviado em 23/01/2013 - 13:20h

Pessoal,

Preciso comparar dois arquivos, cada um contendo aproximadamente 3,5 milhões de linhas (irá gerar aprox. 10^12 combinações). A partir da primeira coluna do primeiro arquivo, irei compará-la à primeira do segundo e imprimir a quarta coluna (do 2), caso essa exista.

Por exemplo:
Arq1
p0001
p0002
Arq2
p0001 lala xrx
p0002 lele rxr s0002

Neste caso, apenas o resultado abaixo me interessa:
s0002

Tentei três formas de resolver o problema:

1) Usando grep:

grep -f arq1.txt arq2.txt | awk '$4 ~ /^s/ {print $4}' > output.txt 


Não sei se é a solução apropriada pois está utilizando muito espaço no swap (17gb) e demorando várias horas para terminar.

2) Usando um shell script:

while read arq1t.txt
do
line2=`grep $line1 <arq2.txt`
if ($line2<>"")
then
IS=`echo $line2 | awk '{print $4}' > output.txt`
endif
done <arq1.txt


Mas está dando erro na última linha.

3) Usando um script em AWK:


#!/bin/awk -f
BEGIN {
while((getline line1 < "arq1.txt")>0) {
while((getline line2 < "arq2.txt")>0) {
split(line2,l,/\t/)
if(l[1] ~ line1) {
if(l[4] ~ /^s/) {
saida = sprintf("s%\n",l[4])
print saida > "output.txt"
}
}
}
}
}


Neste, provavelmente pelo uso do getline aninhado, ele só dá uma volta no primeiro While e saí do loop.

Alguma sugestão tanto em termos de eficiência quanto para consertar os erros?

Desde já agradeço,


  


2. Re: Comparar colunas de dois arquivos

Perfil removido
removido

(usa Nenhuma)

Enviado em 23/01/2013 - 13:32h


while read line1
do
line2=$(grep $line1 arq2.txt)
if [ ${#line2} -gt 0 ]
then
echo $line2 | awk '{print $4}' >> output.txt
fi
done < arq1.txt


BOA SORTE!!!


3. Re: Comparar colunas de dois arquivos

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/01/2013 - 19:43h

Se o primeiro arquivo tem 3,5M linhas, eu fico com pena de rodar 3,5M de greps sobre o segundo arquivo, que também tem 3,5M linhas, assim como também fazer 3,5M invocações do awk apenas para imprimir a quarta coluna de uma linha já conhecida.

Se o a primeira linha do primeiro arquivo for composta de campos suficientemente pequenos, eu faria um script em Perl (poderia ser awk, mas eu não o conheço tão bem quanto Perl) que:

1) Lesse o primeiro arquivo e guardasse os elementos da primeira coluna num array associativo.
2) Lesse o segundo arquivo, vendo se o elemento da primeira coluna se cada linha lida existe no array associativo e se a quarta coluan existe. Se sim, imprime a quarta coluna da linha lida.

Como eu disse, o primeiro arquivo não poderia ser muito grande, Supondo que se possa gastar cerca de 1GB de RAM com o script, o primeiro elemento de cada linha do primeiro arquivo teria de ter um tamanho médio um pouco menor do que trezentos caracteres (300*3,5M=1,05G).

Mas há um jeito mais prosaico, sem precisar de arrays associativos nem coisa parecida, mas tão somente sort e o próprio shell: ordene os dois arquivos pela primeira coluna (se quiser, pode já suprimir do segundo arquivo as linhas que não tiverem a quarta coluna antes de ordenar, para poupar tempo), gerando um novo par de arquivos ordenados. Depois disso, você conseguirá, com o próprio shell, percorrer paralelamente percorrer ambos os novos arquivos uma única vez, pulando os elementos de cada linha lida de um deles enquanto eles forem menores do que o elemento de comparação do outro; quando forem iguais, você imprime a quarta coluna da linha que tiver sido lida do novo segundo arquivo.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts