Encontre correspondências para as 5 colunas em um arquivo delimitado por pipe

1
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Eu preciso encontrar registros correspondentes no Arquivo 1 e no Arquivo 2 na coluna 5. Assim, acima, preciso retornar na saída:

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Muito obrigado,

    
por van 14.10.2013 / 14:46

3 respostas

3

Método 1: grep & awk

Você pode usar este snippet para fazer isso:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Detalhes

O bit que usa awk analisa o primeiro arquivo, file1 retirando todas as 5 colunas. Esses valores são usados como uma lista para grep , que imprimirá qualquer linha no segundo arquivo que contenha uma correspondência.

Advertências com este método

Este método corresponderá a qualquer ocorrência da quinta coluna de file1 em file2 .

Método # 2: apenas awk

Outra abordagem que foi usada no site no passado é usar a instalação FNR de awk . É aqui que awk irá iterar mais de 2 arquivos, passando pelo segundo arquivo linha por linha, para cada linha no primeiro.

Uma abordagem como essa faria isso. Coloque o seguinte em um arquivo, cmds.awk :

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

Você pode executar isso da seguinte maneira:

$ awk -F '|' -f cmds.awk file1 file2

OBSERVAÇÃO: você poderia ter usado este padrão awk :

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

Exemplo

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Advertências com este método

Essa abordagem só pode manipular uma única instância de cada endereço de email de file1 . Portanto, se houver duas linhas que tenham o mesmo valor para a quinta coluna, isso não conseguirá distinguir entre elas. Isso parece aceitável, considerando suas necessidades no OP.

Participe & classificar

Você também pode fazer isso usando join e sort .

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

Isso usará o separador | e unirá os arquivos classificados na quinta coluna. Essa abordagem imprime as correspondências de file1 e file2 , por isso usamos sed para dividir a segunda partida do final.

Exemplo

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578
    
por 14.10.2013 / 15:01
1

Eu faria tudo em perl:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -a ativa a divisão automática de campos na matriz @F .
  • -F'\|' define o delimitador de campo para -a para | .
  • Para cada linha processada, salve o quinto campo (índices de matriz começam em 0 em perl) como uma chave de hash ( $k{$F[4]}++ e incremente seu valor em um. Na segunda vez que um campo for visto, esse valor será 2.
  • O script processará cada linha de ambos os arquivos ( file1 before file2 ) e imprimirá a linha se o quinto campo tiver sido visto antes, ou seja, se $k{$F[4]} for maior que um.

Isso pressupõe que nenhuma quinta coluna seja repetida no arquivo mesmo . Se este não for o caso e algumas colunas puderem ser duplicadas no mesmo arquivo, use isto:

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 
    
por 14.10.2013 / 16:33
0

Se os tamanhos dos arquivos forem comparáveis, a solução ideal é sort ambos os arquivos pelo coluna em que você está interessado e, em seguida, join por essa coluna. Se os tamanhos dos arquivos forem N e M , o tempo de execução assintótico será O(N*log(N)+M*log(M)) .

Se um dos arquivos for muito menor que o outro, a O(N*M) solution nas outras respostas é melhor.

    
por 14.10.2013 / 17:01