Como verificar cada linha dentro de um arquivo delimitado por pipe para ser o mesmo de diferente

1

Eu tenho um arquivo delimitado por pipe que pode ter milhões de registros. O que eu quero fazer é classificar o arquivo e remover se houver alguma linha duplicada.

Depois, preciso verificar as primeiras 32 colunas e ver se o conteúdo da primeira linha corresponde à segunda linha. Se sim, exclua a segunda linha e verifique novamente a primeira linha com a terceira linha (que agora se tornará a segunda linha devido à remoção da linha anterior, já que era a mesma). se isso também for o mesmo, remova a terceira linha também e continue a comparar a primeira linha com as linhas subseqüentes do arquivo até obtermos uma incompatibilidade. Por exemplo: Arquivo de Entrada:

a|a1|a2|a3|a4|...|a32|[email protected]
a|a1|a2|a3|a4|...|a32|[email protected]$1553:2015-02-14 
a|a1|a2|a3|a4|...|a32|[email protected]:2015-03-01 
a|a1|a2|a3|a4|...|a32|[email protected]$121:2015-01-31 
a|a1|a2|a3|a4|...|a32|[email protected]$293:2015-02-28 
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
b|b1|b2|b3|b4|...|b32|[email protected]:2014:05:24 
c|c1|c2|c3|c4|...|c32|[email protected] 
c|c1|c2|c3|c4|...|c32|$200:2011:12:06 
c|c1|c2|c3|c4|...|c32|[email protected]$214:2001:01:31 

Existem 33 campos no exemplo acima e "..." é usado para representar a continuidade. Então, aqui, como você vê, as primeiras 4 linhas são as mesmas (comparando apenas até o campo número 32 que é mostrado no exemplo com um valor de "a32"). Então eu preciso manter apenas o primeiro e excluir outros. Da mesma forma, para as colunas que começam com b , temos 5 registros iguais, portanto, exclua os últimos 4 e mantenha o primeiro. Para os registros que começam com c , temos apenas 3 registros, por isso, precisamos excluir os últimos 2 e manter o 1º. Por isso, o arquivo de saída seria algo assim:

Arquivo de saída necessário:

a|a1|a2|a3|a4|...|a32|[email protected]
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24 
c|c1|c2|c3|c4|...|c32|[email protected] 

Eu estava pensando em usar um comando regular de loop e sed para fazer isso, mas isso retarda o processo significativamente. Então, existe uma maneira de usar ack e tornar essa busca / manipulação mais rápida?

    
por mdx 08.05.2015 / 05:59

2 respostas

4

Classifique as chaves de 1 a 32 (-k1, 32), com barra vertical como delimitador -t'|' .
-u significa: produza somente a primeira linha de uma execução igual ( de teclas combinadas).
Veja man sort para detalhes das opções de sort .

sort -t'|' -k1,32 -u infile

O código acima, claro, resulta em uma saída ordenada.
No entanto, se você quiser manter a mesma sequência de linhas encontradas pela primeira vez, use o arquivo de entrada:

nl -s'|' -ba infile | sort -t'|' -k2,5 -u | sort -t'|' -k1 -n | cut -d'|' -f2-

nl prefixos números de linha sequenciais. Esses números de linha são cut após as etapas sort .
Observe que a saída desse segundo método é a mesma que a solução Perl do terdon .

    
por 08.05.2015 / 07:12
1

A abordagem sort de Peter é quase certamente a mais eficiente, sugiro que você a use. Por uma questão de diversidade, aqui está uma solução Perl:

perl -F"\|" -lane  'push @G,$_ unless ++$k{join("\|",@F[0..31])}>1;
                    END{print join "\n",@G}' file 
    
por 08.05.2015 / 11:12