Encontre correspondências para as 5ª colunas em arquivos de delimitação de tubulação

Encontre correspondências para as 5ª colunas em arquivos de delimitação de tubulação
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|

Preciso encontrar registros correspondentes no Arquivo 1 e no Arquivo 2 na coluna 5. Portanto, do exposto acima, preciso retornar na saída:

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

Muito obrigado,

Responder1

Método nº 1: grep e awk

Você pode usar este trecho 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 awkanalisa o primeiro arquivo, file1retirando todas as quintas colunas. Esses valores são então usados ​​como uma lista para grep, que imprimirá quaisquer linhas no segundo arquivo que contenham uma correspondência.

Advertências com este método

Este método corresponderá a qualquer ocorrência da 5ª coluna de file1in file2.

Método nº 2: simplesmente estranho

Outra abordagem que foi usada no site no passado é usar o awkrecurso FNR da. É aqui que awkirá iterar em 2 arquivos, passando pelo segundo arquivo linha por linha, para cada linha do primeiro.

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

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

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

Você pode então executar isso da seguinte maneira:

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

OBSERVAÇÃO:Você poderia ter usado este awkpadrão:

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 lidar com uma única instância de cada endereço de e-mail do file1. Portanto, se houver 2 linhas com o mesmo valor para a 5ª coluna, não será possível distingui-las. Isso parece aceitável, dados os seus requisitos no OP.

Junte-se e classifique

Você também pode fazer isso usando joine sort.

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

Isso usará o separador |e juntará os arquivos classificados na 5ª coluna. Essa abordagem imprime as correspondências de file1e file2, então usamos sedpara cortar a segunda correspondência 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

Responder2

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|
  • -aativa a divisão automática de campos no array @F.
  • -F'\|'define o delimitador de campo -apara |.
  • Para cada linha processada, salve o 5º campo (os índices do array começam em 0perl) como uma chave hash ( $k{$F[4]}++e aumente seu valor em um. Na segunda vez que um campo for visto, esse valor será 2.
  • O script irá processar cada linha de ambos os arquivos ( file1antes file2) e imprimir a linha se o 5º campo já tiver sido visto antes, ou seja, se $k{$F[4]}for maior que um.

Isso pressupõe que nenhuma quinta coluna seja repetida dentro domesmoarquivo. Se este não for o caso e algumas colunas puderem estar 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 

Responder3

Se os tamanhos dos arquivos forem comparáveis, a solução ideal ésortambos os arquivos pela coluna que você está interessado e entãojoin-los por essa coluna. Se os tamanhos dos arquivos forem Ne Mo tempo de execução assintótico for O(N*log(N)+M*log(M)).

Se um dos arquivos for muito menor que o outro, a O(N*M)solução nas outras respostas será melhor.

informação relacionada