Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I search and replace across multiple lines with Perl?

$ perl --version
This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

$ echo -e "foo\nbar" > baz.txt
$ perl -p -e 's/foo\nbar/FOO\nBAR/m' baz.txt
foo
bar

How can I get this replacement to work?

like image 332
Gabe Kopley Avatar asked May 24 '13 19:05

Gabe Kopley


People also ask

How do I match multiple lines in Perl?

Solution. Use /m , /s , or both as pattern modifiers. /s lets . match newline (normally it doesn't). If the string had more than one line in it, then /foo.

How do I search and replace in Perl?

Performing a regex search-and-replace is just as easy: $string =~ s/regex/replacement/g; I added a “g” after the last forward slash. The “g” stands for “global”, which tells Perl to replace all matches, and not just the first one.

What does Perl 0777 do?

And 0777 will force Perl to read the whole file in one shot because 0777 is not a legal character value. -- This option must be used in conjunction with either the -n or -p option. Using the -a option will automatically feed input lines to the split function. The results of the split are placed into the @F variable.


2 Answers

You can use the -0 switch to change the input separator:

perl -0777pe 's/foo\nbar/FOO\nBAR/' baz.txt

-0777 sets the separator to undef, -0 alone sets it to \0 which might work for text files not containing the null byte.

Note that /m is needless as the regex does not contain ^ nor $.

like image 89
choroba Avatar answered Oct 22 '22 11:10

choroba


It has to do with the -p switch. It reads input one line at a time. So you cannot run a regexp against a newline between two lines because it will never match. One thing you can do is to read all input modifying variable $/ and apply the regexp to it. One way:

perl -e 'undef $/; $s = <>; $s =~ s/foo\nbar/FOO\nBAR/; print $s' baz.txt

It yields:

FOO
BAR
like image 31
Birei Avatar answered Oct 22 '22 10:10

Birei