Search code examples
perl

Multiline search replace with Perl


I know this kind of questions have been asked already many times before. The reason why I come here again is that I feel like I've missed something simple and fundamental.

Is it possible to make this kind of search-replace routine better. For example without opening same file twice. Also speed related advices are welcome.

Please notice that this works with multiline matches and replaces also multiline strings.

#!/bin/perl -w -0777

local $/ = undef;

open INFILE, $full_file_path or die "Could not open file. $!";
$string =  <INFILE>;
close INFILE;

$string =~ s/START.*STOP/$replace_string/sm;

open OUTFILE, ">", $full_file_path or die "Could not open file. $!";
print OUTFILE ($string);
close OUTFILE;

Solution

  • This kind of search and replace can be accomplished with a one-liner such as -

    perl -i -pe 's/START.*STOP/replace_string/g' file_to_change
    

    For more ways to accomplish the same thing check out this thread. To handle multi-line searches use the following command -

    perl -i -pe 'BEGIN{undef $/;} s/START.*STOP/replace_string/smg' file_to_change
    

    In order to convert the following code from a one-liner to a perl program have a look at the perlrun documentation.

    If you really find the need to convert this into a working program then just let Perl handle the file opening/closing for you.

    #!/usr/bin/perl -pi
    #multi-line in place substitute - subs.pl
    use strict;
    use warnings;
    
    BEGIN {undef $/;}
    
    s/START.*STOP/replace_string/smg;
    

    You can then call the script with the filename as the first argument

    $perl subs.pl file_to_change
    

    If you want a more meatier script where you get to handle the file open/close operations(don't we love all those 'die' statements) then have a look at the example in perlrun under the -i[extension] switch.