Remove a segunda linha onde as primeiras poucas colunas são idênticas no arquivo grande

0

Eu tenho um arquivo parecido com isto:

A 1 abc
A 1 def
A 2 ttt
B 2 ppp
B 2 qqq

Gostaria de manter a primeira linha quando as duas primeiras chaves são idênticas, algo assim:

A 1 abc
A 2 ttt
B 2 ppp

Encontrei uma pergunta anterior que resolveu isso. No entanto, meu arquivo é de 1,2 GB e estou correspondendo nas primeiras 19 colunas. Então, quando eu corro isso:

  awk  '!array[$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19]++' infile > outfile

Eu entendo isso:

cmd. line:2: (FILENAME=infile FNR=287807) fatal: dupnode: r->stptr: can't allocate memory (Not enough memory)

Obviamente, não posso dividir o arquivo para processar porque não sei onde estão as duplicatas. Estou disposto a trocar velocidade pela memória para resolver isso. (O arquivo é de cerca de 1,6 milhões de linhas).

    
por innocentunremarkable 28.01.2016 / 17:31

4 respostas

3

Como seu arquivo parece estar classificado:

sort -m -u -k 1,2 < file

-m para mesclagem não tenta classificar o arquivo, mas com -u (para exclusivo ) combinado com -k 1,2 para especificar uma chave de classificação consistindo nos dois primeiros campos (use -k 1,19 para os primeiros 19 campos), estamos removendo duplicatas nos dois primeiros campos.

Se o arquivo não estiver classificado (pelo menos nesses dois campos), basta soltar o -m . O resultado acabará sendo classificado embora. A classificação será dispendiosa, mas deverá ter um bom nível de memória, pois sort recorre ao uso de arquivos temporários para classificar arquivos grandes (você precisa de espaço livre em disco em /tmp (ou $TMPDIR )).

    
por 28.01.2016 / 17:40
0

A combinação das colunas que são idênticas para formar um índice funciona? Com o seu acima, por exemplo. nós poderíamos fazer -

 awk '{ind=""; for(i=1; i<3; i++) {ind=ind" "$i }  if (!arr[ind]) arr[ind]=$3  } END{for (i in arr) print i, arr[i]}'

  A 1 abc
  A 2 ttt
  B 2 ppp

você precisará mudar o loop acima para combinar os índices que você precisa.

    
por 28.01.2016 / 19:37
0

Para ocasiões futuras, você pode fazer isso ... e você economiza o problema de arquivos gigantes com matrizes. Cada vez que o campo um altera seu valor, a matriz é excluída.

BEGIN{
    xd=""; 
}
{
    id=$1;

    if (id != xd)
    {
        for (x in arr)
        {
            print x,arr[x];
        }

        delete arr; #Each time the field one changes its value
        xd=id;
    }
    ind="";
    for (i=1; i<3; i++)
    {
        ind=ind $i;
    }
    if (!arr[ind])
    {
        arr[ind]=$3;
    }

}

END {
        for (x in arr)
        {
            print x,arr[x];
        }
}

Saída:

$ awk -f script.awk file.txt
A1 abc
A2 ttt
B2 ppp
    
por 29.01.2016 / 17:22
0

Experimente:

awk '_a[$1" "$2]++==0'  < filename
    
por 29.01.2016 / 17:49

Tags