The s flag: dotAll mode
The s flag makes the dot match line terminators as well as everything else. It changes the dot only, which is why a negated character class was already crossing newlines without it.
At a glance
- Flag letter
- s
- Property
- RegExp.prototype.dotAll
- Added in
- ES2018
- Affects
- the dot, and only the dot
- Character classes
- unaffected, [^"] already matched a newline with or without s
- Portable equivalent
- [\s\S], which works in every engine and is scoped to one position
In detail
By default the dot matches every character except the four line terminators: \n, \r, U+2028 and U+2029. That exclusion is why a pattern such as /<a>.*<\/a>/ quietly stops at the end of a line. Setting s removes the exclusion, and the dot then matches literally anything.
It is not a free upgrade, because the dot gets greedier in both directions. Against a document with several links, /<a>.*<\/a>/s matches from the first opening tag all the way to the last closing tag, spanning everything in between. If a greedy dot was already a problem on one line, the s flag makes it a problem across the whole file.
The part that is easy to miss is that character classes never had the restriction. [^"] means any character that is not a double quote, and a newline is not a double quote, so a quoted string pattern already ran across lines. Turning on s to fix that kind of pattern changes nothing, because the class was never the thing holding it back.
Before ES2018 the idiom was [\s\S], read as whitespace or not whitespace, which together cover every character. It still has one advantage over the flag: it applies at exactly one position in the pattern instead of changing the behaviour of every dot in it, and it compiles in engines that never got dotAll.
Examples
"a\nb".match(/a.b/); // null
"a\nb".match(/a.b/s)[0]; // "a\nb"
// A negated class was never restricted in the first place.
/"[^"]*"/.exec('"one\ntwo"')[0]; // '"one\ntwo"'"<a>\nx\n</a>".match(/<a>([\s\S]*?)<\/a>/)[1]; // "\nx\n"Only this one position is allowed to cross lines. Every other dot in the pattern keeps its default meaning.
Things that catch people out
- Adding s to a pattern built from negated character classes fixes nothing, because [^x] already matched newlines. When that happens the real bug is somewhere else in the pattern.
- With s set, .*? still crosses lines. A lazy scan that used to stop politely at the end of a line now runs on into the next one.
- The s flag is per pattern, not per dot. If only one position should span lines, write [\s\S] there and leave the flag off.
Try it: Regex Tester
Type a pattern and a test string, watch every match highlight as you go, read a plain English breakdown of each token, and check the numbered and named groups it captured.
Regex Tester
LOCAL · Browser-OnlyTest and debug regular expressions with live matching and highlights
Related Regex syntax
All regex syntax →The dot: any character except a line terminator
What the dot matches by default, the four characters it skips, how the u and s flags change it, and why it needs no escape inside a character class.
\S: non whitespace, and the [\s\S] any character trick
\S is the complement of \s, which makes it a blank check in one character. Paired with \s it also gives the standard match anything class.
The m flag: multiline anchors
What multiline mode changes about ^ and $, which line terminators JavaScript counts, and why the m flag never makes the dot match a newline.
The u flag: Unicode mode
What the u flag changes about how a pattern is parsed, the escape forms it unlocks, and the previously tolerated syntax it turns into a hard error.
The y flag: sticky matching at lastIndex
How the sticky flag anchors a match to the current lastIndex, why it is the right tool for a hand written tokenizer, and how it behaves alongside g.
The d flag: capture group start and end offsets
What the d flag adds to a match result, how indices.groups mirrors named captures, and when the extra offsets are worth asking the engine for.
Tools for this
- Regex Tester Free online regex tester - test and debug regular expressions with live matching and highlights
- Regex Playground Regex playground with live match highlighting, named groups, find and replace, and shareable links