Reputation: 19
I have two files like below:
file1:
column1 column2
---------------
h1 0
h2 0
h3 0
h4 0
file2:
column1 column2
---------------
h1 1
h2 1
I want to compare these two files and write a new file, which will look like below:
column1 column2
---------------
h1 1
h2 1
h3 0
h4 0
Whats the best way to do it, since reading the files to array and looping over wouldn't exactly get the file3 output.
Upvotes: 1
Views: 63
Reputation: 40718
Assuming the first field on each line in each file is a "key" that indicates whether a line in file1.txt
should be replaced by a line in file2.txt
, you could try:
use feature qw(say);
use strict;
use warnings;
my %lines;
my @lines;
my $fn = 'file1.txt';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
while (my $line = <$fh>) {
chomp $line;
my ( $key, @rest ) = split " ", $line;
push @{ $lines{$key} }, $. ;
push @lines, $line;
}
close $fh;
my $fn2 = 'file2.txt';
open ( my $fh2, '<', $fn2 ) or die "Could not open file '$fn2': $!";
while( my $line = <$fh2> ) {
chomp $line;
my ( $key, @rest ) = split " ", $line;
if ( exists $lines{$key} ) {
for my $line_no (@{ $lines{$key} }) {
$lines[$line_no -1] = $line;
}
}
}
close $fh2;
say for @lines;
Output:
h1 1
h2 1
h3 0
h4 0
Edit: To also set all lines which is not updated by file2.txt
to "$key 0":
[...]
my %used_keys;
while( my $line = <$fh2> ) {
chomp $line;
my ( $key, @rest ) = split " ", $line;
if ( exists $lines{$key} ) {
for my $line_no (@{ $lines{$key} }) {
$lines[$line_no -1] = $line;
}
$used_keys{$key} = 1;
}
}
close $fh2;
delete @lines{ keys %used_keys };
for my $key (keys %lines) {
for my $line_no (@{ $lines{$key} }) {
$lines[$line_no -1] = "$key 0";
}
}
[...]
Upvotes: 1