1

I would like to read an input file and then delete a line if it matches my regex. and have the file saved without that line.

I have written

open(my $fh, '<:encoding(UTF-8)', $original_file_path or die "Could not open file $original_file_path $!";

while (my $line = <$fh> ) {
    chomp $line;
    if ($line ~=/myregex/){
        delete line from file
    }
}

Thank you

yankel
  • 135
  • 9
  • You cannot "delete a line in the middle of a file". You can copy the data to a new file and during the copy operation omit lines meeting your criteria. To replace the original file, at the end of the copy operation delete the original and rename the copy. I believe Perl has an option to do this automatically. – Jim Garrison Mar 19 '17 at 15:51

2 Answers2

6

You can modify a file in place by using -i flag.

In your case, a simple one liner would do:

perl -i -ne 'print unless /myregex/' the_name_of_your_file

As mentioned by PerlDuck, if you wish to keep a copy the original file, it's possible: add an extension after the -i flag, like -i.bak or -i~, and then original file will be kept with this extension after its name.

You can find more information about inplace file modification on perlrun.

Note that if you are using Windows (MS-DOS), you will need to specify an extension for the backup file, that you are free to delete afterward. See this link.

You can obtain the same behavior in a script by setting $^I to a value different than undef. For instance:

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

{
    local @ARGV = ( $original_file_path );
    local $^I = ''; # or set it to something else if you want to keep a backup
    while (<>) {
        print unless /myregex/
    }
}

I've used local @ARGV so if you already had something in @ARGV, it won't cause any troubles. If @ARGV was empty, then push @ARGV, $original_file_path would be fine too.


However, if you have more stuff to do in your script, you might prefer a full script over a one-liner. In that case, you should read your input file, and print the lines you want to keep to another file, then move the second file to the first.

Community
  • 1
  • 1
Dada
  • 6,313
  • 7
  • 24
  • 43
  • 2
    You can also add an (optional) extension to the `-i` switch, like `perl -i.bak -ne ...`. Then the original (unchanged) file is kept with a `.bak` extension (in case you messed up your regex). – PerlDuck Mar 19 '17 at 15:31
  • @Borodin Whups, which part? The whole inplace editing mechanism? – Dada Mar 19 '17 at 17:20
  • @Borodin, ThisSuitIsBlackNot Thank you both, I've updated my answer. – Dada Mar 20 '17 at 08:14
4

There are some modules that can make your life easier. E.g. here's a solution using Path::Tiny:

use Path::Tiny;

path($original_file_path)->edit_lines_utf8(sub {
    if (/myregex/) {
        $_ = '';
    }
});
melpomene
  • 84,125
  • 8
  • 85
  • 148