views:

312

answers:

3

For my program, I'm attempting to replace the value of a specific hash in an external file with a newly created value. The external file has the value tab-delimited from the key, and I had read the hash in from the external file. I've been looking around online, and this is the closest way I could figure out how to do it, yet it doesn't seem to work.

            open(IN, ">>$file") || die "can't read file $file";
            while (<IN>) {
            print IN s/$hash{$key}/$newvalue/;
            }
           close (IN)

I'm not quite sure what I'm missing in this formula.

A: 

You are trying to read and write to the same file, that is not going to work. You have to read, substitute then write in another file. Afterwards, you can replace the input file by the one you've just written if you really want one file.

Keltia
Ah, I see. Then is there a way that I can simply append to a value in an external file? That's all I need, I just expected that substitution could accomplish that task.
That's just a variation on the same problem so you'll get the same answer. It is actually a FAQ for Perl.
Keltia
A: 

This won't be efficient, but it should work, unless my perl-fu is bad:

open(IN, "<<$file") || die "can't read file $file";
open(OUT, ">>${file}.tmp") || die "can't open file $file";
while (<IN>) {
    print OUT s/$hash{$key}/$newvalue/;
}
close(IN);
close(OUT);
exec("mv ${file}.tmp $file");

There might be a command to do the move for you in perl, but I'm not a perl guy.

FryGuy
I find that approach interesting, I know you're not a perl person but if you know, would the new file have all the content of the original file just with the necessary parts substituted?
Yes it will because if the substitution does not occur because the value is not found, then `$_` is unchanged then gets written to `OUT`
Keltia
BTW, the function you want is rename(OLD,NEW)
Keltia
For some odd reason, it's telling me it can't read the file now.
Use unlink and rename (rename old spare; rename new old; unlink spare).
Jonathan Leffler
It still tells me that it can't read the file, and it's at the first line of this piece of code that it triggers the problem.Tie::File is helping for substitution, but since it operates with arrays, I'm getting repeat values on more than one run of it.
+3  A: 

Tie::File can fix this for you.

use Tie::File;

tie @array, 'Tie::File', $file or die "Could not tie $file: $!";

for (@array) {
    s/$hash{$key}/$newvalue/;
}
untie @array;
Leon Timmermans