I have 2 files in the exactly the same format and the same data except for 1 column.
Example row of file 1:
"1/30/2017 11:14:55 AM",Valid customer,jim.smith,NY,1485771295
Example row of file 2:
"1/26/2017 8:02:01 PM",Valid customer,jim.smith,NY,1485457321
Of course the files have other rows but what I am interested in is the following:
I want to remove from file 2 all rows that are about the same entity i.e. $3
and exist in file 1 with a later timestamp and keep the rest.
In the example lines you can see that the row in file 1 is newer as we see from the date string of column 1. Now the last integer in the row is the actual epoch of column 1 so this column can be used for e.g. comparing the dates and sorting.
I can accomplish this by scripting e.g in perl something like the following:
#!/usr/bin/perl
use strict;
use warnings;
my $file_a = "file1";
my $file_b = "file2";
open my $file_a_h, $file_a or die "Could not open $file_a";
sub timestamp_users {
my ($fh) = @_;
my %recs;
while ( my $line =<$fh> ) {
my @items = split ",", $line;
my $user = $items[3];
$recs{$user} = $items[5];
}
return \%recs;
}
my $file_a_recs = timestamp_users($file_a_h);
close $file_a_h;
open my $file_b_h, $file_b or die "Could not open $file_b";
my $file_b_recs = timestamp_users($file_b_h);
close $file_b_h;
my $count = 0;
while (my ($user, $last_time) = each %$file_b_recs) {
if(exists $file_a_recs->{$user} && $last_time >= $file_a_recs->{$user}) {
++$count;
`echo $user >> result.txt`;
}
}
print "count: $count\n";
In this case I just output the users and then I would need to do a grep -v
on file_b to figure out the rows I need.
But is there a way to do this using command line tools?
This approach seems too complicated for me.
Update:
Example row of file 1:
"1/30/2017 11:14:55 AM",Valid customer,jim.smith,NY,1485771295
"1/26/2017 5:06:11 AM",New customer,john.doe,CA,1485403571
"1/30/2017 4:14:30 AM",New customer,tim.jones,CO,1485746070
Example row of file 2:
"1/26/2017 8:02:01 PM",Valid customer,jim.smith,NY,1485457321
"1/30/2017 11:09:36 AM",New customer,tim.jones,CO,1485770976
"1/30/2017 11:14:03 AM",New customer,john.doe,CA,1485771243
"1/30/2017 11:13:53 AM",New customer,bill.smith,CA,1485771233
Expected output:
"1/30/2017 11:14:03 AM",New customer,john.doe,CA,1485771243
"1/30/2017 11:09:36 AM",New customer,tim.jones,CO,1485770976
"1/30/2017 11:13:53 AM",New customer,bill.smith,CA,1485771233
file1
so for each ID ($3
) there's just one line infile1
then you can simply runawk -F, 'NR==FNR{z[$3]=$5;next}$5>=z[$3]' file1 file2
$5
for each$3
while readingfile1
then it readsfile2
and it prints the line if the condition$5>=z[$3]
is true (that is if the current$5
isge
than the value of$5
fromfile1
corresponding to the same$3
) - iow it removes the lines for which that condition is false.NR==FNR
is a logical condition then{z[$3]=$5;next}
is the code block and because we have a second file we can have after the code block another logical condition?next
statement that prevents the 2nd condition to be evaluated while processing the 1st file. BasicallyNR==FNR
means as long asF
ile lineN
umbeR
is equal to combined/aggregate input lineN
umbeR
(i.e. this condition is true only for the 1st file) do{something;next}
andnext
skips the commands that follow and reads in the next line, starting from the beginning. So the 2nd condition$5>=z[$3]
is evaluated only for the lines in 2nd file and when true the default action is executed (print)