Flags: case, multiline, dotall, verbose

Regular expressions · Practical · 10 min

Flags fix the most common 'why doesn't it match across lines?' problems and make long patterns readable.

Flags (modifiers) change how a whole pattern behaves. The common ones exist in most flavours under similar letters:

  • i ignore case. Python: re.IGNORECASE.
  • m multiline: ^ and $ match at every line start and end, not just the string ends. Python: re.MULTILINE.
  • s dotall: . also matches newline. Python: re.DOTALL.
  • x verbose: whitespace in the pattern is ignored and # starts a comment, so complex patterns can be laid out over several lines. Python: re.VERBOSE; not available in JavaScript.

Flags can also be set inside the pattern: (?i)abc, or scoped to a group as (?i:abc). Python requires global inline flags at the very start of the pattern.

JavaScript adds flags of its own:

  • g global: needed for matchAll and for replace to change every match. It makes the regex object stateful through lastIndex, which surprises people who reuse a /g regex with test().
  • y sticky: match only at lastIndex.
  • u Unicode mode and v (ES2024) its stricter successor with set operations in classes.
  • d records start and end indices for groups.

Combine flags with | in Python (re.I | re.M) or by listing letters in JavaScript (/x/gimu).

Example

import re

text = "Title\nfirst line\nSecond line"
print(re.findall(r"^\w+", text))                    # ['Title']
print(re.findall(r"^\w+", text, re.M))              # ['Title', 'first', 'Second']
print(re.findall(r"line$", text, re.M | re.I))      # ['line', 'line']
print(re.search(r"Title.*line", text))              # None: . stops at \n
print(re.search(r"Title.*line", text, re.S).group().count("\n"))   # 2

phone = re.compile(r'''
    \(?(\d{3})\)?   # area code, optional parentheses
    [\s.-]?         # separator
    (\d{3})[\s.-]?(\d{4})
''', re.VERBOSE)
print(phone.search("call (555) 123-4567").groups())  # ('555', '123', '4567')

Remember

  • i ignores case, m makes ^ $ per line, s lets . match newlines
  • Verbose mode (x) allows whitespace and comments inside the pattern
  • In JavaScript, g makes a regex stateful via lastIndex

Watch out for

  • Reusing a /g regex with test() in JavaScript and getting alternating true/false because lastIndex moved.

Check yourself

  1. You need ^ to match at the start of every line of a log. Which flag?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/re.html#flags