regex intermediate

How to use the /m modifier for multi-line anchors in Perl?

Question

How to use the /m modifier for multi-line anchors in Perl?

Understanding the /m Modifier for Multi-line Anchors in Perl Regex

In Perl regular expressions, the /m modifier changes the behavior of the anchors ^ and $ from matching only the start and end of the entire string, to matching the start and end of each line within a multi-line string. This can be particularly useful when dealing with strings containing embedded newline characters (\\n), where you want to find matches on a per-line basis rather than just the whole string.

Default Behavior (Without /m)

By default, Perl treats ^ as the anchor for the start of the entire string, and $ as the end of the entire string. For example, in a multi-line string:


my $text = "Line1\nLine2\nLine3";
if ($text =~ /^Line2$/) {
    print "Matched Line2\n";  # won't print without /m
}

This won't match because ^Line2$ tries to match the whole string exactly, which it is not.

Using the /m Modifier

When you add the /m modifier, ^ and $ match the start and end of any line within the string, not just the string boundaries:


my $text = "Line1\nLine2\nLine3";

if ($text =~ /^Line2$/m) {
    print "Matched Line2 with /m modifier\n";  # prints this line
}

Here:

  • ^ matches the position immediately after a newline character or the start of the string
  • $ matches the position immediately before a newline character or the end of the string

This lets you treat each line separately without splitting the string into lines manually.

Common Use Cases and Gotchas

  • Line-by-line matching: When parsing logs, config files, or multi-line input, /m lets you use anchors to target specific lines.
  • Interaction with /s modifier: The /s modifier causes . to match newline characters (normally it does not). /m affects only anchors, so they are often used together for complex multi-line regexes.
  • Beware outputting matches: Without /m, ^ and $ do NOT match within lines. This is a very common pitfall where people expect line-based matching but forget the /m modifier.
  • Unicode and different newline types: The /m modifier works based on the newline characters \\n. On Windows, lines ending in \\r\\n may require normalization or slightly different handling.

Complete Runnable Example:


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

# Multi-line string with embedded newlines
my $text = "First line\nSecond line\nThird line";

print "Without /m:\n";
if ($text =~ /^Second line$/) {
    print "Matched 'Second line' without /m\n";
} else {
    print "No match without /m\n";
}

print "\nWith /m:\n";
if ($text =~ /^Second line$/m) {
    print "Matched 'Second line' with /m modifier\n";
} else {
    print "No match with /m\n";
}

print "\nMatching all lines starting with 'S':\n";
# Matching all lines starting with 'S' using global matching and /m
while ($text =~ /^S.*$/mg) {
    print "Found line: $&\n";
}

Explanation

  • /^Second line$/ tries to match the entire string exactly to "Second line" which fails.
  • /^Second line$/m allows matching "Second line" as a line within the multi-line string because ^ and $ match the start/end of each line, not just the whole string.
  • The while loop with /mg uses the g (global) flag to find all matches on lines starting with "S".

Summary

The /m modifier changes ^ and $ anchors from matching only the start/end of the string to matching the start/end of each line within a string. It is essential when working with multi-line strings and line-by-line pattern matching in Perl regex. Remember, /m affects only anchors and not the behavior of . (dot), which is controlled by /s.

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
(empty)
STDERR
(empty)

Was this helpful?

Related Questions