skip to content

Explain the difference between Pattern.MULTILINE (?m) and Pattern.DOTALL (?s) in Java regex. Which anchors/metacharacters does each affect?

level: middleimportance: must knowfreq 65%

answer

  1. MULTILINE = ^ and $ per line
  2. DOTALL = '.' matches newline too
  3. (?m) anchors, (?s) dot
  4. 's' = Perl 'single line', Java name DOTALL — confusing pair
  5. Independent flags; combine as (?ms)

basics

~20 s

MULTILINE makes ^ and $ match at the start and end of every line, not just the whole input. DOTALL makes the dot '.' match newline characters too. They control different things and are often confused.

solid answer

~50 s

These two flags are frequently mixed up because both relate to newlines, but they affect completely different metacharacters. MULTILINE (Pattern.MULTILINE, inline (?m)) changes the line anchors ^ and $: by default ^ matches only the very start of input and $ only the very end (before a trailing newline); with MULTILINE they also match at the start and end of each line within the input. DOTALL (Pattern.DOTALL, inline (?s) — 's' for 'single line', a Perl-ism) changes the dot: by default '.' matches any character except a line terminator; with DOTALL '.' also matches newlines, so a pattern can span lines. A useful memory hook: 'm' touches anchors, 's' touches the dot. They are independent and can be combined when you want both line-aware anchors and a dot that crosses lines. Neither affects how \n itself is matched literally.

code

java · 18 lines
java
import java.util.regex.*;

String text = "first\nsecond\nthird";

// MULTILINE: ^ matches the start of each line
Matcher m = Pattern.compile("^\\w+", Pattern.MULTILINE).matcher(text);
while (m.find()) System.out.println(m.group()); // first, second, third

// Without MULTILINE, only the first line start matches
Matcher m2 = Pattern.compile("^\\w+").matcher(text);
System.out.println(m2.find() + " " + (m2.find() ? "more" : "only one")); // true only one

// DOTALL: '.' crosses newlines
Matcher d = Pattern.compile("(?s)first.*third").matcher(text);
System.out.println(d.matches()); // true

// Without DOTALL, '.' stops at the newline
System.out.println(Pattern.compile("first.*third").matcher(text).matches()); // false

go deeper

for a junior

Knows MULTILINE relates to ^/$ and DOTALL relates to the dot; may need a reminder which is which.

for a middle

Clearly distinguishes the two, picks the right one for a task, and knows the inline forms (?m)/(?s).

for a senior

Explains the Perl naming history, line-terminator semantics, interaction with UNIX_LINES, and combines (?ms) deliberately.

for a principal

Reasons about correctness/security of multiline parsing (e.g. anchoring user-supplied multi-line input), catastrophic-backtracking risk with (?s).* patterns, and when regex is the wrong tool for multi-line structured text.

## Background terms - An **anchor** is a regex token that matches a *position*, not a character. `^` anchors to a start and `$` to an end. - The **dot** `.` is a metacharacter meaning "any single character." - A **line terminator** is a newline-type character. In Java's default mode that's `\n`, but also `\r`, `\r\n`, and a few Unicode line separators (unless UNIX_LINES restricts it to just `\n`). ## Default behavior (no flags) - `^` matches only at the **beginning of the entire input**. `$` matches only at the **end of the entire input** (technically just before a final line terminator). So in a 3-line string, `^` matches once at position 0. - `.` matches **any character except a line terminator**. So `.` will not cross a `\n`. ## MULTILINE — `Pattern.MULTILINE`, inline `(?m)` This flag redefines the **anchors only**. With MULTILINE on: - `^` matches at the start of input *and* right after every line terminator (i.e., the start of each line). - `$` matches at the end of input *and* right before every line terminator (the end of each line). Nothing else changes. The dot still won't cross newlines. Use MULTILINE when you want to find, say, every line that starts with `#`. ## DOTALL — `Pattern.DOTALL`, inline `(?s)` The name is confusing: the inline letter is `s` (from Perl's "**s**ingle line" mode), yet the Java constant is `DOTALL`. This flag redefines the **dot only**: with DOTALL on, `.` matches **any** character *including* line terminators. It does **not** touch `^`/`$`. Use DOTALL when you want a pattern to span multiple lines, e.g. matching everything between `<pre>` and `</pre>` across line breaks: `(?s)<pre>(.*?)</pre>`. ## Why they're confused Both flags involve newlines, and Perl/PCRE call DOTALL's inline form "single-line" while MULTILINE is "multi-line" — so people assume they're opposites or two halves of one switch. They are **not**: they govern different metacharacters and are fully independent. You can have neither, either, or both. ## Combining them `Pattern.MULTILINE | Pattern.DOTALL` (or `(?ms)`) gives you both line-aware anchors *and* a dot that crosses lines simultaneously — useful for line-anchored extraction where the captured body may itself contain newlines. ## Deriving the answer Ask: do I need `^`/`$` to fire per line? → MULTILINE. Do I need `.` to swallow newlines? → DOTALL. The two questions are separate, so pick independently. Mnemonic: **m** = anchors (Multi-line means many line starts), **s** = dot (Single-line means treat the whole thing as one line so the dot ignores newlines).

  • You want to capture an HTML block that spans several lines using <div>(.*?)</div>. Which flag and why?
    DOTALL ((?s)), so '.' can match the newlines inside the block; MULTILINE wouldn't help because it only affects ^/$.
  • With MULTILINE on, where does $ match in the string "a\nb"?
    After 'a' (end of line 1, before \n) and after 'b' (end of input); without MULTILINE only after 'b'.

saying these in an interview costs you the question

  • Saying MULTILINE makes '.' match newlines — that's DOTALL
  • Saying DOTALL changes ^/$ — it does not
  • Assuming the inline letter for DOTALL is 'd' (it's 's')
  • Believing the two flags are mutually exclusive opposites

context