Multiline search replace with Perl

I know that such questions have been asked many times. The reason I'm here again is because I feel I have missed something simple and fundamental.

Is it possible to do this search procedure? For example, without opening the same file twice. Speed ​​tips are also welcome.

Note that this works with multi-line matches and replaces multi-line strings as well.

#!/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; 
+54
perl
Jun 23 '09 at 5:43
source share
4 answers

This type of search and replace can be done with a single layer, such as

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

For more ways to do the same thing:. To process multi-line searches, use the following command -

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

To convert the following code from a single line to a perl program, see the perlrun documentation.

If you really need to convert this to a working program, just let Perl handle the file open / close 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; 

Then you can call the script with the file name as the first argument

 $perl subs.pl file_to_change 

If you need a more meaty script where you can handle file open / close operations (do we like all these β€œmental” statements), look at the example in perlrun under the -i [extension] switch.

+90
Jun 23 '09 at 5:57
source share

Extract a short answer from comments for anyone looking for quick, single-line text, and the reason Perl ignores their RegEx options from the command line.

perl -0pe 's/search/replace/gms' file

Without the -0 argument, Perl processes line-by-line data line by line , which causes a multiline search to fail.

+33
Nov 28 '17 at 7:17
source share

Whereas you are fully processing the contents of the file:

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

And then do all the processing with $string , there is no connection between how you process the file and how you process the contents. You will have a problem if you open the file for writing before you read it, since opening the file for writing creates a new file, discarding the previous contents.

If all you are trying to do is save in open / close reports and then do as suggested by Jonathan Leffer . If your question is about multi-line search and replace, please specify what the problem is.

+2
Jun 23 '09 at 6:50
source share

You might want to check out this Perl script tested in battle (widely used in production) and having quite a few features, such as:

  • perform multiple replace-search or replace-search-queries
  • search-replace expressions can be given on the command line or read from a file processes several input files
  • go down the directory recursively and perform several search / replace operations for all files
  • user-defined perl expressions are applied to each line of each input file if you want to run in paragraph mode (for multi-line search / replace)
  • interactive mode
  • burst mode
  • optional file backup and backup numbering
  • save modes / owner when run as root
  • ignore symbolic links, empty files, write-protected files, sockets, named pipes and directory names
  • optionally replace strings matching or not matching the given regular expression

https://github.com/tilo/replace_string

+1
Aug 6 '19 at 21:45
source share



All Articles