Python Regex Flags

In many Python regex functions, you see a third argument flags. What are they and how do they work?

Flags allow you to control the regular expression engine. Because regular expressions are so powerful, they are a useful way of switching on and off certain features (e.g. whether to ignore capitalization when matching your regex).

For example, here’s how the third argument flags is used in the re.findall() method:

re.findall(pattern, string, flags=0)

So the flags argument seems to be an integer argument with the default value of 0. To control the default regex behavior, you simply use one of the predefined integer values. You can access these predefined values via the re library:

SyntaxMeaning
re.ASCIIIf you don’t use this flag, the special Python regex symbols \w, \W, \b, \B, \d, \D, \s and \S will match Unicode characters. If you use this flag, those special symbols will match only ASCII characters β€” as the name suggests.
re.A Same as re.ASCII
re.DEBUG If you use this flag, Python will print some useful information to the shell that helps you debugging your regex.
re.IGNORECASE If you use this flag, the regex engine will perform case-insensitive matching. So, if you’re searching for character class [A-Z], it will also match [a-z].
re.I Same as re.IGNORECASE
re.LOCALE Don’t use this flag — ever. It’s depreciated—the idea was to perform case-insensitive matching depending on your current locale. But it isn’t reliable.
re.L Same as re.LOCALE
re.MULTILINE This flag switches on the following feature: the start-of-the-string regex '^' matches at the beginning of each line (rather than only at the beginning of the string). The same holds for the end-of-the-string regex '$' that now matches also at the end of each line in a multi-line string.
re.M Same as re.MULTILINE
re.DOTALL Without using this flag, the dot regex '.' matches all characters except the newline character '\n'. Switch on this flag to really match all characters including the newline character.
re.S Same as re.DOTALL
re.VERBOSE To improve the readability of complicated regular expressions, you may want to allow comments and (multi-line) formatting of the regex itself. This is possible with this flag: all whitespace characters and lines that start with the character '#' are ignored in the regex.
re.X Same as re.VERBOSE

How to Use These Flags?

Simply include the flag as the optional flag argument as follows:

import re

text = '''
    Ha! let me see her: out, alas! he's cold:
    Her blood is settled, and her joints are stiff;
    Life and these lips have long been separated:
    Death lies on her like an untimely frost
    Upon the sweetest flower of all the field.
'''

print(re.findall('HER', text, flags=re.IGNORECASE))
# ['her', 'Her', 'her', 'her']

As you see, the re.IGNORECASE flag ensures that all occurrences of the string ‘her’ are matched—no matter their capitalization.

Related article: Python Regex Superpower – The Ultimate Guide

Do you want to master the regex superpower? Check out my new book The Smartest Way to Learn Regular Expressions in Python with the innovative 3-step approach for active learning: (1) study a book chapter, (2) solve a code puzzle, and (3) watch an educational chapter video.

How to Use Multiple Flags?

Yes, simply add them together (sum them up) as follows:

import re

text = '''
    Ha! let me see her: out, alas! he's cold:
    Her blood is settled, and her joints are stiff;
    Life and these lips have long been separated:
    Death lies on her like an untimely frost
    Upon the sweetest flower of all the field.
'''

print(re.findall('   HER   # Ignored', text,
                 flags=re.IGNORECASE + re.VERBOSE))
# ['her', 'Her', 'her', 'her']

You use both flags re.IGNORECASE (all occurrences of lower- or uppercase string variants of ‘her’ are matched) and re.VERBOSE (ignore comments and whitespaces in the regex). You sum them together re.IGNORECASE + re.VERBOSE to indicate that you want to take both.

Let’s dive into the different flags in more detail by example.

re.ASCII

If you don’t use this flag, the special Python regex symbols \w, \W, \b, \B, \d, \D, \s and \S will match Unicode characters. If you use this flag, those special symbols will match only ASCII characters — as the name suggests.

#########################
# re.ASCII
#########################

s = 'hello wΓΆrld'

print(re.findall('\w+', s))
# ['hello', 'wΓΆrld']

print(re.findall('\w+', s, flags=re.ASCII))
# ['hello', 'w', 'rld']

re.DEBUG

If you use this flag, Python will print some useful information to the shell that helps you debugging your regex.

#########################
# re.DEBUG
#########################

s = 'hello world'

print(re.findall('\w+', s, flags=re.DEBUG))
'''
MAX_REPEAT 1 MAXREPEAT
  IN
    CATEGORY CATEGORY_WORD

 0. INFO 4 0b0 1 MAXREPEAT (to 5)
 5: REPEAT_ONE 9 1 MAXREPEAT (to 15)
 9.   IN 4 (to 14)
11.     CATEGORY UNI_WORD
13.     FAILURE
14:   SUCCESS
15: SUCCESS
['hello', 'world']
'''

re.IGNORECASE

If you use this flag, the regex engine will perform case-insensitive matching. So if you’re searching for [A-Z], it will also match [a-z].

#########################
# re.IGNORECASE
##########################

s = 'HELLO world'

print(re.findall('[a-z]+', s))
# ['world']

print(re.findall('[a-z]+', s, flags=re.IGNORECASE))
# ['HELLO', 'world']

re.MULTILINE

This flag switches on the following feature: the start-of-the-string regex ‘^’ matches at the beginning of each line (rather than only at the beginning of the string). The same holds for the end-of-the-string regex ‘$’ that now matches also at the end of each line in a multi-line string.

#########################
# re.MULTILINE
#########################

s = '''hello
world'''

print(re.findall('^[a-z]+', s))
# ['hello']

print(re.findall('^[a-z]+', s, flags=re.MULTILINE))
# ['hello', 'world']

re.DOTALL

Without using this flag, the dot regex ‘.’ matches all characters except the newline character ‘\n’. Switch on this flag to really match all characters including the newline character.

#########################
# re.DOTALL
#########################

s = '''hello
world'''

print(re.findall('.+', s))
# ['hello', 'world']

print(re.findall('.*', s, flags=re.DOTALL))
# ['hello\nworld', '']

re.VERBOSE

To improve the readability of complicated regular expressions, you may want to allow comments and (multi-line) formatting of the regex itself. This is possible with this flag: all whitespace characters and lines that start with the character ‘#’ are ignored in the regex.

#########################
# re.VERBOSE
#########################

s = 'hello world'

print(re.findall('.+ #I can now write comments', s, flags=re.VERBOSE))
# ['hello world']

Google, Facebook, and Amazon engineers are regular expression masters. If you want to become one as well, check out our new book: The Smartest Way to Learn Python Regex (Amazon Kindle/Print, opens in new tab).