Flags, compile and verbose patterns

re · Practical · 10 min

Flags fix the most common 'why doesn't it match' problems, and verbose mode keeps long patterns maintainable.

Flags modify how a pattern matches. Pass them as flags= and combine with |:

  • re.IGNORECASE (re.I) case-insensitive matching.
  • re.MULTILINE (re.M) makes ^ and $ match at the start and end of every line, not just the string.
  • re.DOTALL (re.S) makes . match newlines too.
  • re.VERBOSE (re.X) ignores whitespace in the pattern and allows # comments, so you can lay out complex patterns over several lines. Escape literal spaces as \ or use [ ].
  • re.ASCII (re.A) restricts \w, \d, \s, \b to ASCII.

Flags can also be written inline at the very start of the pattern: (?i), (?m), (?x); or scoped to part of it: (?i:abc)def.

re.compile(pattern, flags) returns a Pattern object with the same methods (search, findall, sub...). Module-level functions cache compiled patterns internally, so compiling is not mainly about speed. It helps readability: define named patterns once at module level, and the methods accept pos and endpos arguments for searching inside a region.

Never use plain-string flags in a positional slot: since 3.13, count, maxsplit and flags given positionally in sub, subn and split trigger a DeprecationWarning.

Example

import re

text = "Name: Ann\nname: Bob\nAGE: 31"
print(re.findall(r"^name: (\w+)", text, flags=re.I | re.M))   # ['Ann', 'Bob']
print(re.findall(r"^name: (\w+)", text))                      # []

html = "<p>one\ntwo</p>"
print(re.search(r"<p>(.*)</p>", html))                   # None
print(repr(re.search(r"<p>(.*)</p>", html, re.S).group(1)))  # 'one\ntwo'

PHONE = re.compile(r"""
    \(?(\d{3})\)?   # area code, optional parentheses
    [\s.-]?         # separator
    (\d{3})[\s.-]?(\d{4})
""", re.VERBOSE)
print(PHONE.findall("(555) 123-4567 and 555.987.6543"))
# [('555', '123', '4567'), ('555', '987', '6543')]
print(PHONE.search("x 555 123 4567", pos=2).groups())  # ('555', '123', '4567')

Remember

  • re.I, re.M, re.S, re.X, re.A change matching; combine with |
  • MULTILINE affects ^ and $; DOTALL affects .
  • re.compile gives reusable, documented Pattern objects; VERBOSE allows comments

Watch out for

  • Forgetting that whitespace is ignored in VERBOSE mode, so a literal space in the pattern silently disappears.

Check yourself

  1. You search a multi-line string with r'^ERROR' but only the first line is checked. Which flag fixes it?

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