Skip to Content
Course content

113: Common Regex Recipes for Validation

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Think of regex validation like a bouncer at a high-end club. The bouncer doesn't just look at you and guess if you're allowed in; they have a very specific checklist. "Are you wearing a collared shirt? Is your ID valid? Are you on the guest list?" If you fail even one of those specific criteria, you aren't getting through the door. The bouncer isn't interested in who you are as a person—they only care if you match the pattern required for entry.

In Python, re.fullmatch() is your bouncer. Unlike re.search(), which just looks for a pattern anywhere in the string, fullmatch ensures the entire input string conforms to your rules from start to finish. If there's one extra character at the end that doesn't fit, the whole thing is rejected. This is exactly what you want when you're validating user input.

The Bread and Butter: Emails and Passwords

I'll be the first to tell you: writing a "perfect" email regex is a rabbit hole that can swallow your entire afternoon. The actual RFC specification for emails is surprisingly complex. However, for 99% of the apps you'll build, you just need to make sure it looks like an email. Here is a recipe I use most of the time:

import re

def is_valid_email(email):
    # This checks for: characters + @ + characters + . + characters
    pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
    return bool(re.fullmatch(pattern, email))

print(is_valid_email("dev_mentor@example.com"))  # True
print(is_valid_email("bad-email@com"))           # False

Now, passwords are a different beast. You usually aren't looking for one simple pattern, but rather a set of requirements: "At least one uppercase, one lowercase, one digit, and at least 8 characters." To do this in one regex, we use positive lookaheads (?=...). This tells the regex engine: "Look ahead to see if this exists, then jump back to the start and keep checking the rest of the pattern."

def is_strong_password(password):
    # Lookahead for digit, lookahead for upper, lookahead for lower, then length check
    pattern = r'^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,}$'
    return bool(re.fullmatch(pattern, password))

print(is_strong_password("Password123")) # True
print(is_strong_password("pass123"))     # False (No uppercase)

Taming Phone Numbers and Dates

Phone numbers are a nightmare because everyone formats them differently. Some use dashes, some use parentheses, some start with +1. The trick here is to make the delimiters optional using the ? quantifier.

def is_valid_phone(phone):
    # Optional +, optional 1, optional parens, optional separators
    pattern = r'^\+?1?\s*\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$'
    return bool(re.fullmatch(pattern, phone))

# These all pass the bouncer
print(is_valid_phone("(555) 123-4567"))
print(is_valid_phone("5551234567"))
print(is_valid_phone("+1 555.123.4567"))

For dates, I usually suggest using the datetime module for actual validation, but if you need to quickly check if a string follows the YYYY-MM-DD format before processing it, a simple digit-count regex is your best bet:

def is_iso_date(date_str):
    pattern = r'^\d{4}-\d{2}-\d{2}$'
    return bool(re.fullmatch(pattern, date_str))

A Word of Warning on Over-Engineering

I've seen developers spend days crafting a 200-character regex to validate a credit card number, only to realize that the credit card provider has a dedicated library that does it better and handles the checksum logic. Regex is great for format validation, but it's terrible for logic validation. It can tell you if a date looks like 2023-02-31, but it can't easily tell you that February 31st doesn't exist. Use regex to filter the noise, but use Python logic to verify the truth.




📋 Practical Task

Building a User Registration Input Validator

You are building a sign-up form for a new platform. You need to write a validation function validate_user_data(username, zip_code) that checks if the provided inputs meet the following strict requirements:

  • Username: Must be 3 to 15 characters long and contain only alphanumeric characters (letters and numbers). No spaces or special characters allowed.
  • Zip Code: Must be exactly 5 digits (standard US zip code).

The function should return True only if both inputs are valid, and False otherwise.

import re

def validate_user_data(username, zip_code):
    # Your code here
    pass

# Test cases to verify your work:
print(validate_user_data("Coder123", "90210"))  # Expected: True
print(validate_user_data("Co", "90210"))        # Expected: False (Username too short)
print(validate_user_data("Coder_123", "90210")) # Expected: False (Invalid character '_')
print(validate_user_data("Coder123", "9021"))   # Expected: False (Zip code too short)
print(validate_user_data("Coder123", "ABCDE"))  # Expected: False (Zip code not digits)
Rating
0 0

There are no comments for now.

to be the first to leave a comment.