bash comparando múltiplas colunas em dois arquivos com tamanho diferente

3

Eu tenho o seguinte conjunto de dados no arquivo de texto

data.txt

d1,40,gold
d2,30,silver
d3,20,bronze
d4,10,iron
d5,5,wood
d6,20,gold
d7,10,wood
d8,5,gold
d9,10,silver
 .
 .
 .

def.txt

gold,40
silver,30
bronze,20
iron,10
wood,5

O que eu preciso é comparar os dados com o meu arquivo de definição, e adicionar status como "ok" ou "nok" no arquivo principal. Como o arquivo de dados é muito grande, sou capaz de descobrir com loop while, mas está demorando muito tempo. Existe alguma maneira otimizada?

data.txt

d1,40,gold,ok
d2,30,silver,ok
d3,20,bronze,ok
d4,10,iron,ok
d5,5,wood,ok
d6,20,gold,nok
d7,10,wood,nok
d8,5,gold,nok
d9,10,silver,nok
    
por user261334 01.02.2015 / 07:16

1 resposta

5

Por meio do comando único awk , eu acho que seria mais rápido do que usar um while-loop. Você pode testar o quão rápido é o comando time em frente ao comando e veja se é rápido;)

awk -F, 'NR==FNR{ arr[$2]=$2 $1; next } 
    { print $0, (arr[$2]==$2 $3?"ok":"nok") }' OFS=, def.txt data.txt
d1,40,gold,ok
d2,30,silver,ok
d3,20,bronze,ok
d4,10,iron,ok
d5,5,wood,ok
d6,20,gold,nok
d7,10,wood,nok
d8,5,gold,nok
d9,10,silver,nok

Explicação:

  • NR é definido como 1 quando o primeiro registro é lido por awk e incrementado para cada próximo registro em arquivos de entrada únicos ou múltiplos até que todas as leituras sejam concluídas.

  • FNR é definido como 1 quando o primeiro registro é lido por awk e incrementado para cada próximo registro de leitura no arquivo atual e redefinido como 1 para o próximo arquivo de entrada se várias entradas arquivos.

  • , então NR == FNR é verdadeiro apenas para o primeiro arquivo def.txt

  • arr[$2]=$2 $1 ; cria uma matriz associativa chamada arr com a chave como $2 e copia os segundo e primeiro campos como seu valor.

  • O token next pula para executar o restante dos comandos e eles serão executados apenas para o (s) próximo (s) arquivo (s), exceto o primeiro.

  • Este print $0 imprime a linha inteira de data.txt e (arr[$2]==$2 $3?"ok":"nok") (conhecido como operador Ternary ( condition?"if-true":"if-false" ) verifica se o valor da chave em arr[$2] era igual a valores de $2 $3 (segundo e terceiro campos) em data.txt e depois imprime "ok" else "nok" .

  • Isso também funcionará se o arquivo data.txt e os arquivos def.txt não forem sort-ed .

por devWeek 01.02.2015 / 14:34