Code of the Day
BeginnerPractical matching

The dot and flags

Understand the dot wildcard's exact behaviour and how flags i, g, m, s, and x modify pattern matching.

Regular ExpressionsBeginner9 min read
Recommended first
By the end of this lesson you will be able to:
  • Predict exactly what . matches and when it does not match newlines
  • Apply the i flag for case-insensitive matching
  • Use the g flag to find all matches rather than just the first
  • Switch line vs string anchoring with the m flag
  • Enable dotall mode with the s flag

The dot . and regex flags are two of the most frequently used — and most frequently misunderstood — features in a regex pattern. This lesson pins down exactly what they do.

The dot in depth

Outside a character class, . matches any single character except a newline (\n):

/h.t/.test("hat");     // true  — 'a' matches .
/h.t/.test("h\nt");    // false — newline does not match .
/h.t/.test("h t");     // true  — space matches .
/h.t/.test("h");       // false — . requires exactly one character

The dot is a wildcard, not a "skip anything" operator. It consumes exactly one character — no more, no less. This matters when combining it with quantifiers: /.+/ matches one or more of any character (except newline).

Overusing . is a common beginner mistake. When you want "any letter" or "any digit," use a character class ([a-z], \d) rather than . — it makes the pattern's intent explicit and avoids accidental matches. Reserve . for genuine "I don't care what this character is" situations.

Inside a character class, . is a literal dot:

/[.]/.test(".");   // true  — literal dot
/[.]/.test("a");   // false — only matches a period

This is a useful trick for matching a literal dot without escaping: [.] is more readable to some people than \..

Flags

Flags appear after the closing / in a JavaScript regex literal, or as options passed to the regex constructor. They modify how the entire pattern behaves.

i — case-insensitive

Without i, /hello/ does not match "Hello". With it:

/hello/i.test("Hello");      // true
/hello/i.test("HELLO");      // true
/^[a-z]+$/i.test("MixedCase"); // true — character ranges also become case-insensitive

The i flag is the quickest way to handle user input where you do not want to normalise case first.

g — global (find all matches)

Without g, .match() and .exec() return only the first match. With g, you get every non-overlapping match:

"one two three".match(/\w+/);    // ["one"]
"one two three".match(/\w+/g);   // ["one", "two", "three"]

String.prototype.replace also respects g:

"aabbcc".replace(/[a-c]/g, "x");  // "xxxxxx"
"aabbcc".replace(/[a-c]/, "x");   // "xabbcc" — only first

When using .exec() in a loop with the g flag (an older pattern), the regex object maintains a lastIndex property that advances after each call. Modern code usually prefers String.prototype.matchAll() which returns an iterator of all match objects cleanly.

m — multiline

Makes ^ and $ match at the start and end of each line rather than just the start and end of the entire string:

const log = "INFO: started\nERROR: failed\nINFO: done";

log.match(/^ERROR.*/);    // null — ERROR is not at string start
log.match(/^ERROR.*/m);   // ["ERROR: failed"]
log.match(/^INFO.*/gm);   // ["INFO: started", "INFO: done"]

The m flag is most useful when processing multi-line text where you want to work line by line.

s — dotall (dot matches newline)

Makes . match newline characters too, so it truly matches any character:

/hello.world/.test("hello\nworld");    // false — newline blocked by .
/hello.world/s.test("hello\nworld");   // true  — s flag enables dotall

The s flag is useful when matching content that spans multiple lines, like extracting a block between two markers:

const html = "<div>\n  content here\n</div>";
html.match(/<div>.*<\/div>/s);  // matches the whole block

u — unicode

Enables full Unicode mode. In JavaScript, without u, certain Unicode escapes and character class behaviour are limited:

/^\p{L}+$/u.test("café");   // true — \p{L} is Unicode letter category
/^\p{Emoji}$/u.test("😀");  // true

The u flag is important for non-ASCII text — names, emoji, and international content. Without it, some Unicode patterns are silently wrong.

x — extended / verbose (Python and some others, not in JavaScript)

Not available in JavaScript. In Python, the re.VERBOSE flag (re.X) lets you add whitespace and comments inside a pattern to improve readability:

import re
pattern = re.compile(r"""
    \d{4}   # year
    -
    \d{2}   # month
    -
    \d{2}   # day
""", re.VERBOSE)

This is invaluable for long, complex patterns that would otherwise be incomprehensible.

Flag combinations

Flags stack — just append them:

/\d+/gi    // global + case-insensitive (i is irrelevant for digits, but valid)
/^error/gim // global + case-insensitive + multiline

In Python, combine flags with |:

re.search(pattern, text, re.IGNORECASE | re.MULTILINE)

Flags in the RegExp constructor

When building a pattern dynamically, pass flags as the second argument:

function findAll(text, term) {
  const re = new RegExp(term, 'gi');
  return text.match(re) || [];
}
JavaScript — editable, runs in your browser

Flag quick reference

FlagEffect
iCase-insensitive matching
gFind all matches, not just the first
m^/$ match line starts/ends (not just string start/end)
sDotall — . also matches \n
uFull Unicode mode
xVerbose mode with whitespace/comments (Python/Ruby, not JS)

Where to go next

Next: common patterns — a practical catalogue of real-world patterns for emails, URLs, dates, numbers, and more.

Finished reading? Mark it complete to track your progress.

On this page