← Back to Blog

15 Python Regex Patterns Every Developer Should Know

March 19, 2026 3 min read By CodeTidy Team

The Regex Riddle: Why 9 out of 10 Developers Use Regex Wrong

We've all been there - staring at a wall of text, trying to extract a specific pattern, and wondering why our regex isn't working as expected. Regex can be a powerful tool, but it's often misunderstood and misused. In this article, we'll cover the top 15 Python regex patterns every developer should know, along with some best practices to keep in mind.

Table of Contents

  • Email and URL Patterns
  • IP Addresses and Phone Numbers
  • Named Groups and Lookahead/Lookbehind
  • re.compile Best Practices
  • Common Pitfalls and Troubleshooting

Email and URL Patterns

When it comes to validating user input, email and URL patterns are some of the most common use cases for regex. Here's a simple example:

import re

email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
url_pattern = r"^https?://[^\s]+$"

email = "test@example.com"
url = "https://www.example.com"

if re.match(email_pattern, email):
    print("Email is valid")
if re.match(url_pattern, url):
    print("URL is valid")

In this example, we define two patterns: one for email addresses and one for URLs. The ^ symbol matches the start of the string, and the $ symbol matches the end. The re.match function returns a match object if the string matches the pattern.

IP Addresses and Phone Numbers

IP addresses and phone numbers have specific formats that can be matched using regex. Here's an example:

ip_pattern = r"^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
phone_pattern = r"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$"

ip = "192.168.1.1"
phone = "(123) 456-7890"

if re.match(ip_pattern, ip):
    print("IP address is valid")
if re.match(phone_pattern, phone):
    print("Phone number is valid")

In this example, we define two patterns: one for IP addresses and one for phone numbers. The (?:) syntax is used to group parts of the pattern without creating a capture group.

Named Groups and Lookahead/Lookbehind

Named groups and lookahead/lookbehind assertions are powerful features in regex that can help make your patterns more readable and efficient. Here's an example:

pattern = r"(?P<name>[a-zA-Z]+) (?P<age>\d+) years old"
text = "John 30 years old"

match = re.match(pattern, text)
if match:
    print(match.group("name"))  # prints "John"
    print(match.group("age"))  # prints "30"

In this example, we define a pattern with two named groups: name and age. The (?P<name>...) syntax is used to define a named group, and the match.group("name") syntax is used to access the group's value.

re.compile Best Practices

The re.compile function can be used to compile a regex pattern into a regex object, which can be used for matching. Here are some best practices to keep in mind:

  • Use re.compile to compile patterns that will be used multiple times.
  • Use the re.DOTALL flag to make the . character match newlines.
  • Use the re.IGNORECASE flag to make the pattern case-insensitive.
pattern = re.compile(r"hello", re.IGNORECASE)
text = "HELLO WORLD"

if pattern.search(text):
    print("Match found")

Common Pitfalls and Troubleshooting

Here are some common pitfalls to watch out for when using regex:

  • Don't forget to escape special characters: The . character has a special meaning in regex, so make sure to escape it with a backslash if you want to match a literal period.
  • Use the re.DOTALL flag: If you want to match newlines, make sure to use the re.DOTALL flag.
  • Test your patterns: Make sure to test your patterns thoroughly to ensure they match what you expect.

Key Takeaways

  • Use re.compile to compile patterns that will be used multiple times.
  • Use named groups and lookahead/lookbehind assertions to make your patterns more readable and efficient.
  • Don't forget to escape special characters and use the re.DOTALL flag when necessary.

FAQ

Q: What is the difference between re.match and re.search?

A: re.match matches the pattern at the beginning of the string, while re.search matches the pattern anywhere in the string.

Q: How do I make my pattern case-insensitive?

A: Use the re.IGNORECASE flag when compiling the pattern.

Q: How do I escape special characters in my pattern?

A: Use a backslash to escape special characters, such as \. to match a literal period.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp