Compare conjuntos de valores de dois arquivos e imprima a saída em um terceiro arquivo usando o awk

2

Eu tenho um problema ao comparar dois arquivos. Vou tentar o meu melhor para explicar. Eu tenho dois arquivos f1 e f2 que eu tenho que comparar com base em dois conjuntos Parâmetro (p) e Valor (v) .

Basicamente, f1 contém uma lista de valores e data e hora para cada um dos parâmetros

  f1.csv
  P,V,TS
  p1,12,10:10:00
  p2,34,10:21:00
  p1,12,10:21:00
  p2,34,10:22:00 
  p1,60,10:35:00
  p3,60,10:36:00
  p4,22,10:38:00
  p4,42,10:40:00    
  p1,60,10:41:00
  p3,58,10:42:00
  p2,55,10:45:00
  p3,58,10:55:00

O arquivo f2 contém o valor / data e hora anterior / mais recente de cada parâmetro. Cada parâmetro tem apenas uma ocorrência neste arquivo. Para maior clareza, RTS (Real Time Stamp) & UTS (carimbo de hora atualizado).

  f2.csv
  P,V,RTS,UTS
  p1,12,10:00:00,10:05:00
  p2,34,10:07:00,10:15:00
  p3,60,10:25:00,10:30:00
  p4,22,10:30:00,10:32:00

Agora vou tentar explicar a saída em duas partes. A primeira parte é fácil: para similar (P, V) em f1 & f2, mude o UTS com o último TS. Aqui está o pseudo código:

  for each (P, V) in f1
  {
  #if value exists in f2
  if ((P, V) exists in f2)
  { 
   f2.RTS(P,V)=f2.RTS(P,V)
   f2.UTS(P, V) = f1.TS(P, V)
  } 
  }

Para o valor que existe em f2 e f1 primeira parte do arquivo o / p f3 em []: -

 f3.csv

 [ P,V,RTS,UTS
   p1,12,10:00:00,10:10:00
   p2,34,10:07:00,10:21:00
   p1,12,10:00:00,10:21:00
   p2,34,10:07:00,10:22:00 
   p3,60,10:25:00,10:36:00
   p4,22,10:30:00,10:38:00]

A segunda parte é difícil. Ele lida apenas com arquivo f1: Valores que não existem em f2.

Para valores de f1 (p4,42,10: 40: 00) (p2,55,10: 45: 00) que ocorrem apenas uma vez e não estão em f2 devem ter RTS = UTS = TS como dados na saída mostrada abaixo.

Exemplo: -Para uma única ocorrência

   p4,42,10:40:00,10:40:00

Para valores (p3,58,10: 42: 00), (p3,58,10: 55: 00), (p1,60,10: 35: 00) (p1,60,10: 41: 00 ) que ocorrem duas vezes e não estão em f2, a primeira ocorrência deve ter RTS = UTS = TS e a segunda ocorrência para mesma (P, V) deve ter RTS = (TS de primeira ocorrência de (P, V)) e UTS = TS da segunda ocorrência de (P, V).

Exemplo: primeira ocorrência (p1, 60) em f1.

 p1,60,10:35:00,10:35:00

Segunda ocorrência (p1,60) em f1

 p1,60,10:35:00,10:41:00

A segunda parte de saída esperada:

  f3.csv
 [ P,V,RTS,UTS
   p1,60,10:35:00,10:35:00
   p4,42,10:40:00,10:40:00
   p1,60,10:35:00,10:41:00
   p3,58,10:42:00,10:42:00
   p2,55,10:45:00,10:45:00
   p3,58,10:42:00,10:55:00]

A saída final está anexando os dois arquivos CSV de saída.

Obrigado, qualquer ajuda será apreciada

    
por user71914 09.06.2014 / 10:26

2 respostas

0

Eu usei perl aqui, pois tem estruturas de dados mais flexíveis (hash de hashes de arrays).

use strict;
use warnings;
use v5.10;
use autodie;

my (%f1, @order);
open my $fh, "<", "f1.csv";
while (<$fh>) {
    next if $. == 1;
    chomp;
    my ($p, $v, $ts) = split /,/;
    push @{ $f1{$p}{$v} }, $ts;
    push @order, [$p, $v];
}
close $fh;

my %f2;
open $fh, "<", "f2.csv";
while (<$fh>) {
    print if $. == 1;
    chomp;
    my ($p, $v, $rts, $uts) = split /,/;
    $f2{$p}{$v} = [$rts, $uts];
}
close $fh;

for my $key (@order) {
    my ($p, $v) = @$key;
    if (exists $f2{$p}{$v}) {
        my $uts = shift @{$f1{$p}{$v}}
        say join(",", $p, $v, $f2{$p}{$v}[0], $uts);
    }
}

my @remaining;
for my $p (keys %f1) {
    for my $v (keys %{$f1{$p}}) {
        my ($rts, $uts) = @{$f1{$p}{$v}};
        push @remaining, [$p, $v, $rts, $rts] if $rts;
        push @remaining, [$p, $v, $rts, $uts] if $rts and $uts;
    }
}
say for map {join ",", @{$_->[1]}} 
        sort {$a->[0] cmp $b->[0]} 
        map {[$_->[3], $_]} 
        @remaining;

A execução produz:

P,V,RTS,UTS
p1,12,10:00:00,10:10:00
p2,34,10:07:00,10:21:00
p1,12,10:00:00,10:21:00
p2,34,10:07:00,10:22:00
p3,60,10:25:00,10:36:00
p4,22,10:30:00,10:38:00
p1,60,10:35:00,10:35:00
p4,42,10:40:00,10:40:00
p1,60,10:35:00,10:41:00
p3,58,10:42:00,10:42:00
p2,55,10:45:00,10:45:00
p3,58,10:42:00,10:55:00
    
por 09.06.2014 / 18:21
0

Aqui o código com alguma ajuda do meu amigo.Para algumas referencias.Cheers

  #!/bin/awk -f
  BEGIN{
      FS=","; 
      OFS=",";
       }
      {
             if(NR==FNR)
             {
                a[var]=$1" "$2
                ts[var]=$3
                var++   
              }else if(NR>FNR)
            {
            b[sec]=$1" "$2
            rt[sec]=$3
            ut[sec]=$4
            sec++
            } 
     }
  END{  
  #Code for first part of the o/p
         for(i=0;i<var;i++)
           {
          for(j=0;j<sec;j++)
           {
          if(!(a[i]<b[j]||a[i]>b[j]))
          {   m[a[i]]=1
             print a[i]" "rt[j]" "ts[i]
           }
             }      
           }
  #Code for second part of the o/p
         for(i=0;i<var;i++)
         {
         if(m[a[i]]!=1)
         {
             h[a[i]]++  

            if(h[a[i]]==1)
            {
                rts[a[i]]=ts[i]
                print rts[a[i]]
                print a[i]" "ts[i]" "ts[i]
            }
           else{
                print a[i]" "rts[a[i]]" "ts[i]
                }
          }
          }
      }
    
por 10.06.2014 / 14:54

Tags