http://qs321.pair.com?node_id=11119699


in reply to Delete last line of file with regex

Another variation on the "don't add the line to your string in the first place" concept, rather than using eof, would be to read the lines into an array instead of a scalar, remove the last entry from the array if it matches the regex, and then join the (remaining) lines into a single string:
my @lines = <DATA>; if ($lines[-1] =~ /^##/) { pop @lines; } my $slurp = join '', @lines;

Replies are listed 'Best First'.
Re^2: Delete last line of file with regex
by afoken (Chancellor) on Jul 23, 2020 at 08:18 UTC
    my @lines = <DATA>; if ($lines[-1] =~ /^##/) { pop @lines; } my $slurp = join '', @lines;

    Note that this will keep the entire file twice in memory (except for the very last line if it starts with ##). That's ok if you have only small files or large amounts of memory. But for large files and limited memory, this may get you into an out-of-memory situation.

    See also perlfaq3 and perlfaq5.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      In that case you could seek to a position close to the end-of-file, walk backward until you find a newline, use a regex to see if the last line matches, and if so, remove it. Then, truncate the file at the current position and append the modified string to it. This would work on a file of any size while using a minimal amount of memory.

        You've got the right idea but your algorithm is shittily inefficient. The classical (tried and true) solution is to load blocks, one at a time, starting with the last, and search backwards in the block until the marker is found. This solution involves doing some math (to calculate pos from block size and count), but it's much more efficient than using seek.