Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by McA (Priest) on Oct 10, 2013 at 14:24 UTC
|
Hi,
read the first file line by line. Split the line at the '='. Take the first part as key of a hash and the second as value of that key. Then do the same for the second file. When you hit in the second file a key which was already read than the value gets substituted. When you have read both files print every tuple (key, value) of your resulting hash to the first file.
When you have problems with some of that subtasks show us your code and we'll help you.
McA
| [reply] |
|
|
Thanks guys. Especially McA and Corion. I have this figured. This is what I have done so far and it seems to work. Please suggest any improvements or blunders that I am making with the code.
use strict;
use warnings;
use constant {
FILE_A => './kma',
FILE_B => './kma2',
};
my %a_hash;
my @a_array;
my @b_array;
open my $a_fh, "<", FILE_A;
while (<$a_fh>) {
chomp;
my ($key, $value) = split '=', $_, 2;
$a_hash{$key} = $value;
}
open my $b_fh, "<", FILE_B;
while (<$b_fh>) {
chomp;
my ($key, $value) = split '=', $_, 2;
$a_hash{$key} = $value;
}
open my $c_fh, ">", FILE_A or die $!;
print $c_fh "$_=$a_hash{$_}\n" for (keys %a_hash);
| [reply] [d/l] |
|
|
print $c_fh "$_=$a_hash{$_}\n" for (sort keys %a_hash);
Cheers Rolf
( addicted to the Perl Programming Language)
| [reply] [d/l] |
|
|
Nicely done.
Funny that it felt like a homework assignemnt, showing that homework sometimes does reflect the real world :-).
That said, I can't see any particular issue with yoru code, other than the use of a variable for the file handle, which I'm seeing more and more of in Perl posts here. Has that become the "new normal"?
What you just did with that code, by the way, is essentially re-invent the sort/merge using Perl hashes to take care of all the dirty work for you. :-)
Looking forward to your next Perl issue.
| [reply] [d/l] [select] |
|
|
|
|
Just some suggestions
The use constant part is not needed probably, you can add the filename in the open line (saving some typing).
You have two pairs of variables with the same name for file A and File B ($key, $key, $value, $value). This is probably a source of future troubles.
You don't need to repeat the word array as variable name, if something begins with @ you know yet that is an array, something like "@first" is probable a better choice, (easier to write and read) than "@a_array". Don't use @a either.
You need to add possible spaces to the split regex, and you could probably fill the %hash directly with maybe something like: (untested)
my ($key, $a_hash{$key}) = split /\s*=\s*/, $_, 2;
| [reply] [d/l] |
Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by LanX (Saint) on Oct 10, 2013 at 14:21 UTC
|
> Could someone kindly guide me to the right direction.
Sure! :)
Firstly start with an example that makes sense (why is "world" excluded, it's different!?!) and then show us what you tried so far!
Cheers Rolf
( addicted to the Perl Programming Language)
| [reply] |
|
|
Hi!
I cam across this example which is supposed to put the difference of the two files in b_array. Then i was thinking of merging it. But it still doesn't solve my problem of updating the file with latest values.
use strict;
use warnings;
use constant {
FILE_A => './kma',
FILE_B => './kma2',
};
my %a_hash;
my @a_array;
my @b_array;
open my $a_fh, "<", FILE_A;
while ( my $line ~= <$a_fh> ) {
chomp $line;
$line = /^(.+?);/; # This strips the first field from the line
$a_hash{$1} = 1; # Now, I'll use the first field as my index
+ to my hash
push @a_array, $line; # This adds the line to the end of the arra
+y
}
close $a_fh;
open my $b_fh, "<", FILE_B;
while ( my $line = <$b_fh> ) {
$line ~= /^(.+?);/;
if ( not exists $a_hash{$1} ) {
push @b_array, $line;
}
}
close $b_fh;
my @combined_array = sort (@a_array, @b_array);
print "content of my combined array = @combined_array";
| [reply] [d/l] |
|
|
"world" is excluded because it has been updated by the second file.
| [reply] |
Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by marinersk (Priest) on Oct 10, 2013 at 15:42 UTC
|
Nice homework exercise. Forces you to read a file, write a file, and conceptually divides the I/O from the processing by requiring information from both files before writing the output.
There are many ways to do this, but for such a small amount of data (homework exercise unlikely to exceed your system's memory LOL), I'd agree McA on this one -- a hash is definitely the way to go. That does most of the work for you.
| [reply] [d/l] |
|
|
Actually it is an interesting exercise. What I need this is for remotely configuring my WiFi access points that runs with hostapd. So hostapd has a configuration file called hostapd.conf.
what I want is to send only the modifications in the conf file over a perl socket. I am able to do that already. But now I need to process the downloaded file and merge into the existing conf file and then reboot the AP.
I am new to perl so i am stuck for the time being :)
| [reply] |
Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by Lennotoecom (Pilgrim) on Oct 10, 2013 at 20:27 UTC
|
%hash = map {$_ => 1} <>;
open OUT, '> file3' or die $!;
print OUT for (sort keys %hash);
i wouldn't change the original file1
hence file3 as output | [reply] [d/l] |
|
|
%hash = map {$_ => 1} <DATA>;
print for (sort keys %hash);
__DATA__
A=hello
B=world
B=planet
C=universe
Output:
A=hello
B=planet
B=world
C=universe
... but the expected output is
A=hello
B=planet
C=universe
The input data is basically a two-column input and the keys are in the first column. The hash approach in general is correct, but you need to use the stuff left of the equal sign as key and the rest (or the whole line) as value:
use strict;
my %hash = map {/^(.*)=/ or die "Malformed input: $_"; $1 => $_} <DATA
+>;
print for (sort values %hash);
__DATA__
A=hello
B=world
B=planet
C=universe
| [reply] [d/l] [select] |
|
|
when I wrote that, the author didnt clarify
the tasks clearly yet
if he needs select the name before "="
i would go with code:
%hash = map {/=(\w+)/; $` => $1} <DATA>;
foreach (sort keys %hash){
print "$_ $hash{$_}\n";
}
__DATA__
A=hello
B=world
B=planet
C=universe
| [reply] [d/l] |
Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by hdb (Monsignor) on Oct 14, 2013 at 07:03 UTC
|
perl -ne "/^([^=]+)/ and $_{$1}=$_; END {print sort values %_}" file1
+file2 > file1
| [reply] [d/l] |
Re: Merge the difference between two files and save it on the first file. Also update the first file with info in second file.
by Laurent_R (Canon) on Oct 10, 2013 at 17:07 UTC
|
| [reply] |
|
|
Sorry about that. What I need is that. I have one text file and then I get a second text file. Then I want the contents in the first text file to be updated by the content of the second text file.
| [reply] |