我在比较两个文件时遇到问题。我会尽力解释。我有两个文件f1和f2我必须根据两组进行比较参数(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]
}
}
}
}