Tuesday, April 5, 2011

How do I replace the values of a hash in an external file?

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.

From stackoverflow
  • 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 : That's just a variation on the same problem so you'll get the same answer. It is actually a FAQ for Perl.
  • 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.

    Keltia : 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)
    Jonathan Leffler : Use unlink and rename (rename old spare; rename new old; unlink spare).
  • 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;
    

0 comments:

Post a Comment