Regular Expressions in Python

    Kedar Kabra3 min readUpdated

    A regular expression (regex) is a pattern that describes a piece of text. Python's built-in re module lets you search for, extract, and replace text that matches a pattern. Here's a quick example that finds all the numbers in a string:

    import re
    
    text = "Order 12 pens and 34 books"
    numbers = re.findall(r"\d+", text)   # \d+ means "one or more digits"
    print(numbers)     # ['12', '34']
    

    That \d+ is a regex pattern. Let's learn the building blocks.

    The pattern alphabet

    Patterns are built from ordinary characters plus special symbols. The most useful ones for beginners:

    • \d — any digit (0–9). \d+ means one or more digits.
    • \w — any word character (letter, digit, or underscore).
    • \s — any whitespace (space, tab, newline).
    • . — any single character.
    • + — one or more of the previous item.
    • * — zero or more of the previous item.
    • ? — zero or one (optional).
    • ^ and $ — start and end of the string.
    • [...] — any one character from the set, e.g. [aeiou].

    The r"..." prefix makes a raw string, so backslashes are taken literally. Always use raw strings for regex patterns.

    Core functions in the re module

    import re
    
    text = "Contact: [email protected] or call 9876543210"
    
    # search() finds the FIRST match anywhere, returns a match object or None
    match = re.search(r"\d{10}", text)   # \d{10} = exactly 10 digits
    if match:
        print(match.group())             # 9876543210
    
    # findall() returns ALL matches as a list
    words = re.findall(r"\w+", "one two three")
    print(words)                         # ['one', 'two', 'three']
    
    # sub() replaces matches with new text
    clean = re.sub(r"\d", "*", "PIN 1234")
    print(clean)                         # PIN ****
    

    Matching with quantifiers

    Quantifiers control how many of something to match:

    import re
    
    # {n} exactly n times, {n,m} between n and m times
    print(re.findall(r"\d{4}", "Year 2026 not 26"))    # ['2026']
    print(re.findall(r"\d{1,2}", "1 22 333"))          # ['1', '22', '33']
    

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses

    Groups: extracting parts

    Parentheses (...) create groups so you can pull out specific pieces of a match:

    import re
    
    date = "Today is 30-05-2026"
    
    # Three groups: day, month, year
    match = re.search(r"(\d{2})-(\d{2})-(\d{4})", date)
    if match:
        day, month, year = match.groups()
        print(f"Day: {day}, Month: {month}, Year: {year}")
        # Day: 30, Month: 05, Year: 2026
    

    A practical example

    import re
    
    # Pull all email addresses out of a block of text
    text = """
    Reach us at [email protected] or [email protected].
    Old address: [email protected] was here.
    """
    
    # A simple email pattern: word chars, @, domain, dot, extension
    emails = re.findall(r"[\w.]+@[\w.]+\.\w+", text)
    print(emails)
    # ['[email protected]', '[email protected]', '[email protected]']
    

    This isn't a perfect email validator (those are surprisingly complex), but it works well for extracting addresses from ordinary text.

    Common mistakes

    • Forgetting the raw string: Without r"...", backslashes get misinterpreted. Always write patterns as raw strings: r"\d+".
    • Confusing search and match: re.match() only checks the start of the string; re.search() looks anywhere. Most of the time you want search or findall.
    • Forgetting to check for None: re.search() returns None when there's no match. Calling .group() on None crashes. Always check if match: first.
    • Greedy matching surprises: .* matches as much as possible. If a pattern grabs too much, use the non-greedy .*?.
    • Over-engineering patterns: Regex is powerful but can get unreadable fast. For very simple tasks, plain string methods like .split() or .replace() may be clearer.

    FAQ

    Is regex part of Python or a separate install? It's built in. Just import re — no installation needed.

    Should I compile patterns? For patterns used many times, pattern = re.compile(r"\d+") then pattern.findall(text) is slightly faster. For one-off use, the module functions are fine.

    How do I make matching case-insensitive? Pass the flag re.IGNORECASE, e.g. re.findall(r"python", text, re.IGNORECASE).


    Regex relies on the re module from the standard library — see Modules, Packages & pip. It's also a key tool in Web Scraping Basics with Python for cleaning extracted text. More on the Python learning hub.

    Want to learn this properly? Join the waitlist for our Python course — taught in Jalgaon, beginner-friendly.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses
    Kedar Kabra

    Instructor, Infoplanet

    Kedar Kabra teaches Python at Infoplanet, helping beginners become confident programmers through hands-on, project-first practice.

    Related guides