SKU // 86

JavaScript RegExp Flags

Flags are letters placed after the closing slash that change how the whole pattern behaves: find every match instead of one, ignore case, treat each line separately, and so on. You can combine as many as you need, in any order.

/pattern/flags
/cat/gi                     // global + ignore case
new RegExp("cat", "gi")       // same thing with the constructor

// The Flags

Flag Name Effect
gglobalFind all matches, not just the first
iignore caseA matches a
mmultiline^ and $ match at each line, not just the whole text
sdotAll. also matches line breaks
uunicodeTreat emoji etc. as single characters; enables \p{...}
ystickyMatch only exactly at lastIndex
dindicesReport start/end positions of matches
vunicodeSetsAn upgraded u (new in 2024): set math inside [ ]

The first three, g, i, and m, cover nearly everything you will need.

// g: Global

const text = "red, green, red, blue";

text.replace(/red/, "RED")    // "RED, green, red, blue"   first only
text.replace(/red/g, "RED")   // "RED, green, RED, blue"   all

text.match(/red/)               // ["red"]  (plus extra info: index, input)
text.match(/red/g)              // ["red", "red"]  just the matches
RED, green, red, blue RED, green, RED, blue ["red"] ["red", "red"]

// i: Ignore Case

/hello/.test("Hello World")    // false
/hello/i.test("Hello World")   // true

"JS js Js jS".match(/js/gi)    // ["JS", "js", "Js", "jS"]

// m: Multiline

Normally ^ means "start of the text" and $ means "end of the text." With m, they mean start and end of each line:

const list = "apple\nbanana\navocado";

list.match(/^a\w+/g)    // ["apple"]               only the very start
list.match(/^a\w+/gm)   // ["apple", "avocado"]    start of every line
["apple"] ["apple", "avocado"]

// s: Dot Matches Everything

const note = "Start\nEnd";

/Start.End/.test(note)    // false  (. does not match the line break)
/Start.End/s.test(note)   // true

// u: Unicode

"😀".match(/./g).length     // 2  (split the emoji in half)
"😀".match(/./gu).length    // 1
2 1
Tip
Adding u is a good habit whenever text might contain emoji or non-English letters. It also unlocks \p{L} ("any letter in any language"), covered in RegExp Classes.

// d: Match Indices

The d flag does not change what matches. It adds an indices property to the result, holding the [start, end] position of the match (and of each group, covered in RegExp Groups). The end is one past the last character, just like slice:

const result = "Order 42".match(/\d+/d);
console.log(result[0], result.indices[0]);
42 [6, 8]

// y: Sticky

Every regex has a lastIndex property. With y, the match must start exactly at lastIndex: no searching ahead.

const sticky = /\w+/y;
sticky.lastIndex = 4;
console.log("abc def ghi".match(sticky)[0]);   // starts right at position 4

sticky.lastIndex = 3;
console.log("abc def ghi".match(sticky));        // position 3 is a space: fail

const plain = /\w+/;
plain.lastIndex = 4;
console.log("abc def ghi".match(plain)[0]);    // without y, lastIndex is ignored
def null abc

Sticky matching is mainly used to write tokenizers: programs that read text one piece at a time, like the part of a browser that reads your JavaScript.

// v: Unicode Sets

v is an upgraded u. Everything u does still works, and it adds set math inside square brackets. -- means "minus":

// lowercase letters, minus the vowels
console.log("hello world".match(/[[a-z]--[aeiou]]/gv).join(""));
hllwrld

You can use u or v, but not both: /x/uv is SyntaxError: Invalid regular expression flags.

// Flags for Part of a Pattern

Newer browsers let you turn a flag on for just one group with (?flags:...):

const re = /(?i:w3schools) tutorials/;   // i applies only inside the group

console.log(re.test("W3SCHOOLS tutorials"));   // true: the group ignores case
console.log(re.test("W3Schools Tutorials"));   // false: "tutorials" still needs lowercase
true false

// Reading a Regex's Flags

const re = /x/gi;
re.flags        // "gi"
re.global       // true
re.ignoreCase   // true
re.multiline    // false

There is one true/false property per flag:

globalghasIndicesd
ignoreCaseidotAlls
multilinemstickyy
unicodeuunicodeSetsv
W3Schools errors on its Flags page
  • Its /i example says it searches for "w3schools" but the code uses /is/g.
  • Its group-modifier example /(?i:WShools) tutorials/ is labeled "Returns true," but the typo (no 3, no c) makes it return false.
  • It says /\p{Emoji}/ fails "without the /v flag." It fails without u or v: /\p{Emoji}/u works fine.
  • Its methods table says regex.exec() "returns an Iterator." It returns one match array (or null). matchAll() is the one that returns an iterator (RegExp Methods).

// The g + test() Trap

A regex with g remembers where its last match ended, in a property called lastIndex. Calling test() repeatedly continues from there:

const re = /a/g;

re.test("a")   // true   (lastIndex moves to 1)
re.test("a")   // false  (starts searching at position 1: nothing there)
re.test("a")   // true   (lastIndex had reset to 0)
true false true
Watch out
This flip-flopping causes baffling bugs in validation code. Do not use the g flag on a regex you only call test() with. g is for match, replace, and matchAll.

// Quick Check

What does this log?

console.log("Cat cat CAT".match(/cat/g).length, "Cat cat CAT".match(/cat/gi).length);
Show answer
1 3. Without i, only the lowercase "cat" matches.

Which flag makes ^ match at the start of every line?

  1. g
  2. s
  3. m
  4. y
Show answer
C. m is multiline. s is the one that lets . match line breaks, which is easy to mix up.

Why does the second call return false?

const re = /a/g;
re.test("a");   // true
re.test("a");   // false
Show answer
With g, the regex remembers lastIndex (1 after the first match) and starts the next search there, past the end of "a". Drop the g when you only use test().

// Try It

  1. Click Open Playground and run it. Add flags until every "the", including "The", becomes "THE"
  2. Given a multi-line string of names, list only the lines starting with "J" using ^ and m
  3. Open the g + test() example with its Try it Yourself button, see the flip-flop, then fix it by removing g
  4. Count the characters in "👋🏽hi" with /./g and with /./gu
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:46 AM ET