比较两个文件中的值集并使用 awk 在第三个文件中打印输出

比较两个文件中的值集并使用 awk 在第三个文件中打印输出

我在比较两个文件时遇到问题。我会尽力解释。我有两个文件f1f2我必须根据两组进行比较参数(p)值(v)

基本上f1包含每个参数的值和时间戳列表

  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

文件f2包含每个参数的先前/最新值和时间戳。每个参数在此文件中仅出现一次。为了清楚起见,RTS(实时时间戳)和 UTS(更新时间戳)。

  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

现在我将尝试分两部分解释输出。第一部分很简单:对于 f1 和 f2 中类似的 (P,V),将 UTS 更改为最新的 TS。这是伪代码:

  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)
  } 
  }

对于 [] 中 o/p 文件 f3 的 f2 和 f1 第一部分中存在的值:-

 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]

第二部分很难。它仅处理 f1 文件:f2 中不存在的值。

对于仅出现一次且不在 f2 中的 f1 (p4,42,10:40:00)(p2,55,10:45:00) 中的值,应具有 RTS=UTS=TS,如下面所示的输出所示。

示例:-对于单次出现

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

对于出现的值 (p3,58,10:42:00),(p3,58,10:55:00),(p1,60,10:35:00)(p1,60,10:41:00)两次并且不在 f2 中,第一次出现应有 RTS=UTS=TS,相同 (P,V) 的第二次出现应有 RTS=((P,V) 第一次出现的 TS) 和第二次出现的 UTS=TS (P,V) 的发生。

示例:f1 中第一次出现 (p1,60)。

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

f1 中第二次出现 (p1,60)

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

第二部分预期输出:

  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]

最终输出是附加两个输出 CSV 文件。

谢谢您的帮助,我们将不胜感激

答案1

我在这里使用了 perl,因为它具有更灵活的数据结构(数组哈希的哈希)。

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;

运行它会产生:

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

答案2

这是我朋友的一些帮助的代码。仅供参考。干杯

  #!/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]
                }
          }
          }
      }

相关内容