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

13,966

Solution 1

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 $.

Solution 2

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
Share:
13,966

Related videos on Youtube

Gabe Kopley
Author by

Gabe Kopley

We are hiring at Binti! Ask me about our mission, team, culture, and work :) https://binti.com/careers/software-engineer/ Head of Engineering at Binti https://binti.com [email protected] Organizer and Teacher at Rails School San Francisco https://www.railsschool.org [email protected] Advisor at Coshx Labs https://www.coshx.com [email protected] https://github.com/gkop https://twitter.com/kopley

Updated on September 14, 2022

Comments

  • Gabe Kopley
    Gabe Kopley over 1 year
    $ 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?

    • Jerry
      Jerry almost 11 years
      Try adding the g flag: 's/foo\nbar/FOO\nBAR/gm'.
    • Gabe Kopley
      Gabe Kopley almost 11 years
      @Jerry no, the g option is for global behavior and is not relevant to my problem.