Search code examples
perlin-place

Perl in-place editing produces garbage


I am having trouble with in-place file editing, having browsed the web for a couple of hours without results.

I really don't want to use the general temporary file scheme, i.e. writing everything to a new file and replace the old one. I need modification timestamps to reflect actual changes, permissions and ownership to remain unchanged etc.

If I understand correctly, using $I^ is just a short-hand for the temp-file scheeme - or am I wrong?

The "+<" mode should open the file for both reading and writing.

My test code so far:

#!/usr/bin/perl
use strict;
use warnings;

open(FILE, "+<", "testingfile") or die "$!";

while (<FILE>) {
    print;
    s/world/WORLD/;
    print FILE $_;
    print;
}

The "testingfile" has three lines, and I just want to replace "world" with "WORLD" for now:

hello
world
foo

Result

When I run the Perl script, garbage is produced and the terminal is left hanging until interrupted (Ctrl+C):

hello
hello
foo
foo
o
o
llo
llo
ÈÈ'>jËNgs}>¾ØKeh%P8*   *        +       +      p+      ÑÑÀ+    +       p+      p+      ¨° #!/u8in/puse ct;
ÈÈ'>jËNgs}>¾ØKeh%P8*   *        +       +      p+      ÑÑÀ+    +       p+      p+      ¨° #!/u8in/puse ct;

The "testingfile" now contains:

hello
world
foo
hello
hello
foo

I'm running an old Perl on a SunOS (Solaris) production system:

This is perl, v5.8.4 built for i86pc-solaris-64int

Solution

  • #!/usr/bin/perl
    use strict;
    use warnings;
    
    # getlines
    open(FILE, "<", "testingfile") or die "$!";
    my @lines = <FILE>;
    my $line = "";
    close(FILE);
    
    # open file again but this time for writing
    open(FILE, ">", "testingfile") or die "$!";
    
    # write adjusted text
    foreach $line (@lines) {
        $line =~s/world/WORLD/;
        print FILE "$line";
        print "$line";
    }