/^/

Lesson 18 of 28

Regex Flags

A complete tour of JavaScript regex flags — g, i, m, s, u, y, d, and v — and how to combine them.

7 min read

A regex pattern describes what to match; flags describe how to apply it — case sensitivity, whether to find one match or all of them, how anchors and . behave, and more. Flags go after the closing slash in a literal (/pattern/flags) or as a second argument to the RegExp constructor.

const re1 = /hello/gi;
const re2 = new RegExp("hello", "gi");

re1.test("Hello world"); // true
re2.source; // "hello"
re2.flags; // "gi"

Both forms are equivalent — use the literal syntax when the pattern is known upfront, and new RegExp(...) when you need to build a pattern dynamically (for example, from user input).

The flags, one by one

Flag Name Effect
g global Find all matches instead of stopping at the first
i ignoreCase Match letters regardless of case
m multiline ^ and $ match at the start/end of each line
s dotAll . also matches newline characters
u unicode Treats the pattern as Unicode code points; enables \u{...} and \p{...}
y sticky Match must start exactly at lastIndex, no scanning ahead
d hasIndices Adds a .indices array with start/end positions of each match and group
v unicodeSets Newer (ES2024) superset of u supporting set operations inside character classes

Combining flags

Flags are just letters — order doesn’t matter, and you can combine as many as make sense together:

/^error/gim.test("Warning\nERROR: disk full"); // true, thanks to m + i
cat nap Catnip cathedral
3 matches

Here m lets ^ match at the start of every line, not just the first, and i lets Cat match the pattern cat regardless of case. Try removing m or i in the demo above and watch matches disappear.

dotAll in action

Normally, . refuses to match line-terminator characters like \n. The s flag removes that restriction:

/a.b/.test("a\nb");   // false — . doesn't match \n by default
/a.b/s.test("a\nb");  // true  — s makes . match anything, including \n
a b
1 match

Sticky vs. global

g and y both aim to find repeated matches, but they behave differently: g’s .exec() calls search forward from lastIndex until a match is found anywhere in the remaining string, while y demands the match start exactly at lastIndex — no skipping ahead. Sticky matching is what tokenizers and parsers typically use, since they need to know the match happened right where they expected it.

Tip

The d flag doesn’t change what matches — it just adds extra information (.indices) to the result, telling you the exact start/end character positions of the whole match and each capture group. It’s handy for building things like syntax highlighters that need to know where a match sits, not just what it is.

Predict the flag combination

Given const re = /^\s*todo/im; and the text "Notes\n TODO: ship it", will re.test(...) return true or false? Which two flags are doing the work?

Show solution

It returns true. The m flag lets ^ match at the start of the second line (not just the very beginning of the string), and the i flag lets TODO match the lowercase todo in the pattern. Without m, ^ would only match before "Notes", and the leading whitespace plus TODO on the second line would never be reached.

What’s next

Flags like u unlock a whole category of patterns that go beyond plain ASCII. Next, we’ll dig into Unicode matching — \p{...} property escapes, and why \w alone quietly fails on accented and non-Latin text.

Quick check

Which flag makes ^ and $ match the start and end of each line, rather than only the start and end of the whole string?

Which flag allows the . metacharacter to also match newline characters?