Perl DISCUSSION

Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

Started by gauravflawless Perl regex modifiers/s and /mmultiline matchnon-greedy quantifierregex anchors
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

gauravflawless Perl Forum
#1

I read a whole log file into one string and try to pull out every block between two markers with $text =~ /BEGIN(.*)END/. It only matches when BEGIN and END are on the same line. I also expected /^ERROR/ to find lines that start with ERROR, but it matches only if the file itself starts with it.

Which modifiers do I need, and is there anything else that behaves differently once the string contains many lines?

Community replies 4

Re: Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

#2

Two independent modifiers are involved. By default . matches any character except a newline; /s removes that exception, so .* can run across line breaks. By default ^ and $ anchor only at the start and end of the whole string; /m makes them also match just after and just before every newline inside it.

So /BEGIN(.*)END/s fixes the first pattern and /^ERROR/m fixes the second. They can be combined as /ms when a pattern needs both.

Re: Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

#3

Once .* can cross lines, greediness matters. With three BEGIN...END blocks in the file, /BEGIN(.*)END/s captures from the first BEGIN to the last END, one huge match. Use the non-greedy form .*?, which stops at the nearest END.

To collect all blocks at once, match globally in list context: my @blocks = $text =~ /BEGIN(.*?)END/gs;. With three blocks, scalar(@blocks) is 3. To process them one at a time, use while ($text =~ /BEGIN(.*?)END/gs) { ... } and read $1 inside the loop.

Re: Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

#4

The anchors have a subtlety that matters for validation. Without /m, $ matches at the very end of the string and also just before a newline that ends the string. That means /^\d+$/ accepts "123\n". When the match must cover the entire string, use \A and \z: /\A\d+\z/. These two ignore /m completely; \A is always the start of the string and \z always the absolute end.

Re: Perl regex stops matching at line breaks: what do the /s and /m modifiers actually change?

#5

If the file is large, you do not have to load it into one string. The range operator keeps state between lines: while (<$fh>) { print if /BEGIN/ .. /END/; } prints every line from a line matching BEGIN through the next line matching END, then waits for the next BEGIN. Memory use stays at one line.

When you do need the whole file, read it with my $text = do { local $/; <$fh> };. Adding the /x modifier lets you spread a long pattern over several lines with comments, which helps once the expression grows.

TEP COMMUNITY