joshuakcockrell joshuakcockrell - 6 months ago 21
Perl Question

Replace all text, including newlines, between two strings with perl

I have several hundred readme files which follow a specific format. I need to replace a chunk of text in each one with different content. Everything is working great except I'm unable to select the words if there are newlines

\n
between the words. An example is as follows:

...
this
is

old


content
...


I would like to replace all the text in these files so they look like this

...
new content
...


I have tried the following perl commands but they do not work with the newlines

perl -pi -w -e 's/this(\n|.)*?content/new content/g;' *.txt


I have tried adding the /s tag based on http://stackoverflow.com/a/226601/4975772 (perhaps I'm doing this incorrectly..)

perl -pi -w -e 's/this(\n|.)*?content/new content/gs;' *.txt


Without the "?"

perl -pi -w -e 's/this(\n|.)*content/new content/g;' *.txt


Using (.+?) instead of (\n|.) based on Regex to match any character including new lines

perl -pi -w -e 's/this(.+?)*content/new content/g;' *.txt


Using [\s\S] instead of (\n|.) based on Regex to match any character including new lines

perl -pi -w -e 's/this[\s\S]*content/new content/g;' *.txt


I have tried these expressions inside regexpal.com and they reportedly work perfectly.

regexpal example

If I remove the newlines from the readme files, everything works perfectly for all of these example perl commands. What am I doing wrong?

Answer

You want to add the 0777. So your one liner should be.

perl -0777 -pi -e 's/this.*?content/new content/sg;' *.txt

0777 is a slurp mode. It pass entire files to your script in $_

This is equal to local $/;

 open my $fh,"<","file";
 local $/;
 my $s = <$fh>;

Here the whole file will store into the $s.

Then, no need to add the \n in your pattern. Because s modifier to allow the . to match the any character including newlines.

Comments