Manipulando 3 arquivos usando o awk

8

Considere os seguintes arquivos:

file1 :

boo,8,1024
foo,7,2048

file2 :

foo,0,24,154
noo,0,10,561

file3 :

24,154,7,1024,0

O que eu preciso é ir para File1 e verificar se $2==7 ; se true, use $1 , $2 e $3 de Arquivo1 ; agora eu tenho que comparar se $1 de File1 igual a $1 de File2 ; se for verdade, tenho que usar $3 e $4 de File2 que não existem em File1 , então eu tenho que ir para File3 e verificar se $1 de File3 é igual a $3 de File2 , e $2 de File3 é igual a $4 de File2 ; se sim, então eu tenho que verificar se $2 de File1 é igual a $3 de File3 Então, se esta condição for verdadeira, eu tenho que comparar $3 de File1 com $4 de File3 , se $3 de Arquivo1 for maior que $4 de File3 .

Eu tentei o seguinte script:

cat [file1] [file2] [file3] | 
awk -F, 
'{if(NF==3)
    {if($2==7){a[$1]=$1; b[$1]=$2; c[$1]=$3}
    }else
        {if(NF==4){if(a[$1]==$1){d[$3]=$3; e[$4]=$4}
                  }else
                        {if(NF==5){if(d[$1]==$1 && e[$2]==$2){print a[$1], b[$1], c[$1], d[$1]}}
                        }
                  }

  }'

A saída desejada é:

foo,7,2048,24,154,1024
    
por Eng7 08.09.2015 / 11:11

2 respostas

8

Isso funcionou para mim:

awk -F, 'FNR==1{++f} \
  f==1 && $2==7 {a1[$1]++; a2[$2]=$3; o=$0} \
  f==2 && a1[$1] {o=o","$3","$4; a3[$3]=$4} \
  f==3 && a3[$1] && $2==a3[$1] && a2[$3] && $4<a2[$3] {print o}' \
file1 file2 file3

Explicação :

  • A primeira linha ( FNR==1{++f} ) incrementa o índice do arquivo para determinar posteriormente em qual arquivo somos 1-3.
  • file1: se $2 for igual a 7
    • preencha uma matriz a1 com $1 como índice e a2 com $2 como índice e $3 como valor
    • anote a variável o (saída) com os primeiros 3 campos
  • file2: se $1 de file2 for igual a $1 de file1 (anteriormente gravado em a1 )
    • acrescente $3 e $4 à variável de saída o .
    • preencha uma matriz a3 com $3 como índice e $4 como valor.
  • file3: se:
    • $1 é igual a arquivo2s $3 (índice de a3 )
    • $2 é igual a arquivo2s $4 (valor de a3 )
    • $3 é igual a file1s $2 (índice de a2 )
    • $4 é menor que file1s $3 (valor de a2 )
  • então:
    • imprima o valor de o .
por 08.09.2015 / 12:10
1

Solução de TXR:

@(repeat)
@id,@val0,@val1
@  (next)
@  (skip)
@id,@nil,@val2,@val3
@  (next)
@val2,@val3,@val0,@val4,@val5
@  (require (< (int-str val4) (int-str val1)))
@  (output)
@id,@val0,@val1,@val2,@val3,@val4
@  (end)
@(end)

Executar:

$ txr join.txr file1 file2 file3
foo,7,2048,24,154,1024

Mas o astuto observador notará que o 7 não foi especificado em nenhum lugar no código, aparecendo apenas na saída! Isso porque o código está realmente passando por todos os registros em file1 e imprime todas as combinações que atendem às correspondências e à restrição . O único nos dados de amostra é aquele com val0 sendo 7 .

Se houvesse mais combinações encontradas, poderia ser restrito a apenas o 7 como este:

$ txr -Dval0=7 join.txr file1 file2 file3
foo,7,2048,24,154,1024

# how about 6?
$ txr -Dval0=6 join.txr file1 file2 file3
# no output

A linguagem de extração de padrões TXR fornece aqui uma correspondência grande de padrões com referências anteriores implícitas através da repetição de nomes de variáveis, abrangendo vários arquivos, com padrões de extração de várias linhas e restrições não textuais, além de efeitos colaterais incorporados como saída, e assim por diante.

A solução Awk aceita traduziu com cuidado o TXR Lisp awk macro :

(awk (:begin (set fs "," ofs ","))
     (:let o (a1 (hash :equal-based)) (a2 (hash)) (a3 (hash)))
     (t (mf [orf int-str identity])) ;; map those fields to integers, which can be
     ((and (= arg 1) (= [f 1] 7)) (inc [a1 [f 0] 0])
                                  (set [a2 [f 1]] [f 2])
                                  (set o rec))
     ((and (= arg 2) [a1 [f 0]]) (set o '@o,@[f 2],@[f 3]')
                                 (set [a3 [f 2]] [f 3]))
     ((and (= arg 3)
           [a3 [f 0]]
           (= [f 1] [a3 [f 0]])
           [a2 [f 2]]
           (< [f 3] [a2 [f 2]])) (prn o)))

Executar:

$ txr awkit.tl file1 file2 file3
foo,7,2048,24,154

A parte ,1024 exigida na saída está ausente; o original "Awk Classic" tem esse comportamento.

    
por 13.09.2016 / 07:03