Read the entire file, then print when editing in place?

Most in-place editing examples are single-line, which iterate through a file or files, reading and printing one line at a time.

I cannot find examples of reading the whole file into an array, modifying the array as needed, and then printing the array when using the ^ i switch to edit inplace. When I try to read the entire file from the diamond operator, edit the contents and print all the contents, I find that printing goes to STDOUT instead of ARGVOUT and that ARGVOUT is closed. I can open the same file for output and then print it, but I'm not sure I understand why this is necessary. Here is an example:

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

my $filename = 'test.txt';

push @ARGV, $filename;

$^I = ".bk";

my @file = <>; #Read all records into array
chomp @file;
push @file, qw(add a few more lines);

print join "\n", @file; #This prints to STDOUT, and ARGVOUT is closed. Why?

test.txt, , test.txt , STDOUT.

+3
4

. perlrun.

-i, perl ARGVOUT STDOUT. , , <> <ARGV> readline(ARGV) , ARGVOUT .

<> ( ), perl ARGVOUT STDOUT . , perlrun

#!/usr/bin/perl -pi.orig
s/foo/bar/;

#!/usr/bin/perl
$extension = '.orig';
LINE: while (<>) {
    if ($ARGV ne $oldargv) {
        if ($extension !~ /\*/) {
            $backup = $ARGV . $extension;
        }
        else {
            ($backup = $extension) =~ s/\*/$ARGV/g;
        }
        rename($ARGV, $backup);
        open(ARGVOUT, ">$ARGV");
        select(ARGVOUT);
        $oldargv = $ARGV;
    }
    s/foo/bar/;
}
continue {
    print;  # this prints to original filename
}
select(STDOUT);

my @file = <> , Perl STDOUT.


, , <> eof(ARGV) . eof(ARGV)=1, , , <>:

my @file = ();
while (<>) {
    push @file, $_;
    if (eof(ARGV)) {
        # done reading current file
        @processed_file = &do_something_with(@file);
        # last chance to print before ARGVOUT gets reset
        print @processed_file;
        @file = ();
    }
}
+6
my @file = <>; #Read all records into array

. , *ARGV , $^I .

my @file;
while (<>) {
    push @file, $_;
}
continue {
    if (eof ARGV) {
        chomp @file;
        push @file, qw(add a few more lines);
        print join "\n", @file;
        @file = ();
    }
}

(-) -, ( ) .

undef $/;
while (<>) {
    my @file = split /\n/, $_, -1;
    push @file, qw(add a few more lines);
    print join "\n", @file;
}

.

+3

Tie :: File can also be used to edit the file in place. However, it does not leave a backup copy of the original file.

use warnings;
use strict;
use Tie::File;

my $filename = 'test.txt';
tie my @lines, 'Tie::File', $filename or die $!;
push @lines, qw(add a few more lines);
untie @lines;
+2
source

Editing Perl inplace is much simpler than any of the answers:

sub edit_in_place
{
    my $file       = shift;
    my $code       = shift;
    {
        local @ARGV = ($file);
        local $^I   = '';
        while (<>) {
            &$code;
        }
    }
}

edit_in_place $file, sub {
    s/search/replace/;
    print;
};

if you want to back up then change local $^I = '';tolocal $^I = '.bak';

+1
source

Source: https://habr.com/ru/post/1789598/


All Articles