regex intermediate

How to match across multiple lines with /s modifier in Perl?

Question

How to match across multiple lines with /s modifier in Perl?

In Perl, matching patterns across multiple lines can sometimes be tricky because by default, the dot character . in a regex does not match newline characters. This means if your string contains line breaks (typically \n), the . metacharacter stops matching where the line ends.

To overcome this and allow . to match newline characters, Perl provides the /s modifier (often called the "single-line" mode or "dotall"). When you use /s, the dot matches every character including newline, allowing your match to span multiple lines.

Understanding /s vs /m

  • /s changes . to match any character, including newline \n.
  • /m treats ^ and $ as start/end of any line within the string, not just start/end of the entire string.

They are different and often confused: /s affects how . behaves, /m affects anchors (^ and $).

Example: Matching across multiple lines with /s

Suppose you want to match any content between <start> and <end> tags, even if there are multiple lines inside:

#!/usr/bin/perl
use strict;
use warnings;

my $text = "<start>This is
a multi-line
text<end>";

# Without /s modifier
if ($text =~ /<start>(.*)<end>/) {
  print "Without /s: Matched: '$1'\n";
} else {
  print "Without /s: No match\n";
}

# With /s modifier
if ($text =~ /<start>(.*)<end>/s) {
  print "With /s: Matched: '$1'\n";
} else {
  print "With /s: No match\n";
}

Output:

Without /s: No match
With /s: Matched: 'This is
a multi-line
text'

Explanation:

  • Without /s, .* stops at the first newline, so the whole pattern can't find <end>.
  • With /s, . matches newlines, so .* greedily consumes all characters until it finds <end>.

Common Pitfalls

  • Mixing /s and /m expecting the same behavior—remember, /m does not affect ..
  • Greedy vs lazy matching: .* is greedy and matches as much as possible. For multiple matches in a single string, consider using the lazy quantifier .*?.
  • Line endings on different OS can be \r\n (Windows), so matching \n specifically might miss some cases. Using /s helps because it matches both.
  • If you only want to affect \^ and \$ (line anchors), use /m instead.

Summary

The /s modifier in Perl regex is essential when you want the dot . to match newline characters, enabling matching over multiple lines within a string. It is a simple but powerful tool that helps avoid many common issues when dealing with multiline text data.

Verified Code

Executed in a sandbox to capture real output. • v5.34.1 • 5ms

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
Without /s: No match
With /s: Matched: 'This is
a multi-line
text'
STDERR
(empty)

Was this helpful?

Related Questions