awk - processando dois arquivos

1

Eu tenho dois arquivos que preciso comparar por alguns campos:

arquivo de referência:

42:B:0
43:A:1
44:A:1
45:A:1

arquivo de destino:

42:!:1
43:B:0
44:A:1
45:B:2

O que eu preciso eu já posso conseguir com loop 'while' combinado + awk:

$ cat reference|while IFS=: read a b c;do awk -F: -va=$a -vb=$b -vc=$c '$1==a{if($2!=b){if($3>c)if($2!="!"){ print a":target has bigger $3("$3">"c") and $2 different ("$2")" } else { print a":target has bigger $3("$3">"c") but $2 disabled ("$2")" }}}' target;done
42:target has bigger $3(1>0) but $2 disabled (!)
45:target has bigger $3(2>1) and $2 different (B)

como eu poderia livrar do loop 'while' e processar os dois arquivos no awk diretamente?

    
por DonJ 28.03.2018 / 08:20

2 respostas

1

awk -F: '
    FNR == NR { c2[$1] = $2; c3[$1] = $3; next }
    !($1 in c2) {
        printf("%d: $1 not found in reference\n", $1)
        next
    }
    $3 > c3[$1] && $2 == "!"    {
        printf("%d: target has bigger $3 (%d>%d) but disabled $2 (%s)\n", $1,$3,c3[$1],$2)
        next
    }
    $3 > c3[$1] && $2 != c2[$1] {
        printf("%d: target has bigger $3 (%d>%d) but different $2 (%s)\n", $1,$3,c3[$1],$2)
    }' reference target

Isto lê o arquivo de referência e, em seguida, o arquivo de destino.

Ao ler o arquivo de referência ( FNR == NR ), ele coleta os valores da segunda e da terceira coluna nas duas matrizes c2 e c3 . O índice usado é o valor na primeira coluna.

Ao ler o arquivo de destino ( FNR != NR ), ele compara o valor na terceira coluna com o valor salvo na matriz c3 . Em seguida, ele também compara a segunda coluna com ! ou a segunda coluna salva do arquivo de referência em c2 .

O código também se queixará com uma mensagem adicional se a primeira coluna do arquivo de destino não for encontrada no arquivo de referência.

A saída, dados os dados na pergunta com uma linha de destino adicionada ( 56:C:9 ):

42: target has bigger $3 (1>0) but disabled $2 (!)
45: target has bigger $3 (2>1) but different $2 (B)
56: $1 not found in reference
    
por 28.03.2018 / 08:55
1

paste + awk mágica:

paste -d':' reference target | awk -F':' \
'$1 == $4 && $2 != $5 && $6 > $3{ 
     if ($5 == "!"){ p = "but"; state = "disabled" }
     else { p = "and"; state = "different" }
     printf "%s:target has bigger $3(%d > %d) %s $2 %s (%s)\n", $1, $6, $3, p, state, $5 
}'

A saída:

42:target has bigger $3(1 > 0) but $2 disabled (!)
45:target has bigger $3(2 > 1) and $2 different (B)

Solução de bônus gawk (considerando que o valor do primeiro campo é ordenado e exclusivo):

awk -F':' \
'NR == FNR{ 
    a[NR][1] = $1; a[NR][2] = $2; a[NR][3] = $3; next 
}
$1 == a[FNR][1] && $2 != a[FNR][2] && $3 > a[FNR][3]{ 
   if ($2 == "!"){ p = "but"; state = "disabled" }
   else { p = "and"; state = "different" }
   printf "%s:target has bigger $3(%d > %d) %s $2 %s (%s)\n", $1, $3, a[FNR][3], p, state, $2 
}' reference target
    
por 28.03.2018 / 08:51

Tags