Comparando arquivos csv com a coluna de pesquisa 1, verifique os valores na coluna 2

1

OK, vou tentar explicar o que preciso fazer da melhor forma possível. Basicamente eu tenho dois arquivos CSV, conforme os exemplos abaixo:

Arquivo 1:

Column 1, Column 2
abc     , 123
def     , 234
adf     , 567

Arquivo 2

Column 1, Column 2
abc     , 123
def     , 234
adf     , 578

Eu preciso escrever um script shell ou um comando simples que faça o seguinte:

  1. Classifique os dois arquivos pela coluna 1
  2. linha por linha, faça o seguinte:
    • Usando a coluna 1 no arquivo 1, pesquise esse valor na coluna 1 do arquivo 2.
      1. se encontrado, compare o valor na coluna 2 no arquivo 1 com o valor na coluna 2 do arquivo 2
      2. se corresponder, escreva a coluna 1, coluna 2 e "Validado" na coluna 3 em um arquivo separado
      3. se não corresponder, escreva a coluna 1, coluna 2 e "Falhou" em um arquivo separado

Isso resulta em dois arquivos de saída: o primeiro com tudo que foi encontrado nas correspondências da coluna 1 e da coluna 2 e um segundo arquivo contendo pesquisas da coluna 1 que falharam ou onde a coluna 1 foi encontrada, onde a coluna 2 não coincidiu. então, essencialmente, usando a coluna 1 como chave para verificar a coluna 2.

    
por Veyron 21.03.2017 / 18:08

2 respostas

0

Dados os seguintes arquivos de entrada:

$ cat in1 in2
Column 1, Column 2
abc     , 123
def     , 234
adf     , 567
Column 1, Column 2
abc     , 123
def     , 234
adf     , 578

Primeiro, nós os classificamos; então podemos juntar os dois em um arquivo:

$ sort in1 > in1.sorted; sort in2 > in2.sorted; paste in{1,2}.sorted
Column 1, Column 2  Column 1, Column 2
abc     , 123   abc     , 123
adf     , 567   adf     , 578
def     , 234   def     , 234

awk nos ajudará aqui, mas as vírgulas ficam no caminho. podemos nos livrar deles com sed primeiro:

$ paste in{1,2}.sorted | sed s/,//g
Column 1 Column 2   Column 1 Column 2
abc      123    abc      123
adf      567    adf      578
def      234    def      234

E então podemos despejar isso por meio de um rápido awk :

$ paste in{1,2}.sorted | sed s/,//g | awk '$2 == $4 {print $1,"Validated"}; $2 != $4 { print $1,"Failed"}'
Column Failed
abc Validated
adf Failed
def Validated

Isso também pode ser feito com awk bruto, com a vantagem de poder remover as linhas de cabeçalho e não depender dos mesmos dados na mesma ordem, eliminando a necessidade de classificação:

$ awk 'FNR != 1 && NR == FNR {data[$1]=$3} FNR != 1 && NR != FNR {if(data[$1]==$3) {print $1, "Validated"} else {print $1, "Failed"} }' in{1,2}
abc Validated
adf Failed
def Validated

Isso depende de algumas variáveis e truques incorporados do magic awk relacionados a eles:

  • NR - o número total de registros processados
  • FNR - o número total de registros no arquivo atual processado
  • FNR != 1 - pula a primeira linha de cada arquivo (não trata os cabeçalhos como dados)
  • NR != FNR - é executado somente depois que o primeiro arquivo foi completamente lido e nós começamos a ler os arquivos subseqüentes. Isso nos permite preencher o array data para testes assim que começarmos a mastigar o segundo arquivo.
por 21.03.2017 / 18:25
0

Acho que resolvi isso agora com o seguinte, caso alguém leia isso e precise disso. Obrigado novamente.

FNR == NR {     para (i = 2; i < = NF; i ++) {a [i, $ 1] = $ i}     b [$ 1];     Próximo; } ($ 1 em b) {# verificar se a linha no arquivo2 existia no arquivo1     para (i = 2; i < = NF; i ++) {         if (a [i, $ 1] == $ i)             printf ("% s- > col% d:% s vs% s: válido \ n", $ 1, i-1, a [i, $ 1], $ i);         outro             printf ("% s- > col% d:% s vs% s: Falha \ n", $ 1, i-1, a [i, $ 1], $ i);     }     exclua b [$ 1]; # excluir entradas que são processadas }

END {     para (à esquerda em b) {# aparência que não correspondia         para (i = 2; i < = NF; i ++)             printf ("% s- > col% d:% s vs (em branco): Não igual \ n", esquerda, i-1, a [i, esquerda])     } }

    
por 23.03.2017 / 12:31