Removing a line from a huge file in Perl

I have a huge text file, and the first five lines of it are read below:

This is fist line
This is second line
This is third line
This is fourth line
This is fifth line

Now I want to write something in a random position on the third line of this file, which will replace the characters in this line with the new line I'm writing. I can achieve this with the code below:

use strict;
use warnings;

my @pos = (0);
open my $fh, "+<", "text.txt";

while(<$fh) {
    push @pos, tell($fh);
}

seek $fh , $pos[2]+1, 0;
print $fh "HELLO";

close($fh);

However, I cannot understand using the same approach as I can remove the entire third line from this file so that the texts are read below:

This is fist line
This is second line
This is fourth line
This is fifth line

I do not want to read the entire file into an array, and I do not want to use Tie :: File. Is it possible to achieve my requirement using search and storytelling? The solution will be very helpful.

+4
source share
3 answers

. () , ? , "" "" - . (, , .)

"", , , . . .

use warnings 'all';
use strict;
use File::Copy qw(move);

my $file_in = '...';
my $file_out = '...';  # best use `File::Temp`

open my $fh_in,  '<', $file_in  or die "Can't open $file_in: $!";
open my $fh_out, '>', $file_out or die "Can't open $file_out: $!";

# Remove a line with $pattern
my $pattern = qr/this line goes/;

while (<$fh_in>) 
{
    print $fh_out $_  unless /$pattern/;
}
close $fh_in;
close $fh_out;

# Rename the new fie into the original one, thus replacing it
move ($file_out, $file_in) or die "Can't move $file_out to $file_in: $!";

, . , ( ). . perlfaq5.

, File:: Temp.


, , '+<' , . , (tell) , . seek , , .

, , . , . , .


inode. ,

  • , . . , . , .

  • - ('+<'). , , seek ( , ), . , ,

    truncate $fh, tell($fh); 
    

    . , , , .

, "" "" , .

+7

sed Linux Perl:

my $return = `sed -i '3d' text.txt`;

"3d" .

0

It is useful to see perlrunand see how perl itself modifies the file in place.

Given:

$ cat text.txt
This is fist line
This is second line
This is third line
This is fourth line
This is fifth line

You can apparently "change in place", for example sed, using the switch -iand -pto call Perl:

$ perl -i -pe 's/This is third line\s*//' text.txt
$ cat text.txt
This is fist line
This is second line
This is fourth line
This is fifth line

But if you look at the Perl Cookbook 7.9 recipe (or look at perlrun ), you will see that it is:

$ perl -i -pe 's/This is third line\s*//' text.txt

is equivalent to:

while (<>) {
    if ($ARGV ne $oldargv) {           # are we at the next file?
        rename($ARGV, $ARGV . '.bak');
        open(ARGVOUT, ">$ARGV");       # plus error check
        select(ARGVOUT);
        $oldargv = $ARGV;
    }
    s/This is third line\s*//;
}
continue{
    print;
}
select (STDOUT);                      # restore default output
-1
source

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


All Articles