Regular expressions or regex are a powerful tool for pattern matching within strings. They are ubiquitous in programming and are essential for tasks like data cleaning, validation, and extraction. This comprehensive tutorial will guide you through the fundamentals of regular expressions in Python, covering everything from basic matching to advanced techniques. By the end, you’ll be able to confidently use regex to solve a wide variety of string manipulation problems.
What are Regular Expressions?
Regular expressions are essentially mini-languages designed for pattern matching. Instead of explicitly specifying the exact string you’re looking for, you define a pattern that describes the characteristics of the strings you want to match. This allows for flexibility and scalability, especially when dealing with variable or unpredictable data.
Getting Started with the re
Module
In Python, regular expressions are handled by the re
module. This module provides a set of functions for compiling, matching, and manipulating regular expressions. Let’s start with some basic examples using the core functions: re.search
, re.match
, and re.findall
.
re.search()
: This function searches for the first occurrence of a pattern within a string. It returns a match object if a match is found, otherwise it returnsNone
.
1
2
3
4
5
6
7
8
9
10
11
import re
text = "The quick brown fox jumps over the lazy dog"
pattern = "fox"
match = re.search(pattern, text)
if match:
print("Match found:", match.group(0))
else:
print("Match not found")
re.match()
: Similar tore.search()
, butre.match()
only matches at the beginning of the string.
1
2
3
4
5
6
7
8
9
10
11
import re
text = "The quick brown fox jumps over the lazy dog"
pattern = "The"
match = re.match(pattern, text)
if match:
print("Match found:", match.group(0))
else:
print("Match not found")
re.findall()
: This function finds all occurrences of a pattern within a string and returns them as a list.
1
2
3
4
5
6
7
8
import re
text = "The quick brown fox jumps over the lazy dog"
pattern = "the" # Note: case-sensitive
matches = re.findall(pattern, text, re.IGNORECASE) #re.IGNORECASE flag makes it case-insensitive
print("Matches found:", matches)
Metacharacters and Special Sequences
Regular expressions utilize metacharacters to represent special patterns. These are characters that have a special meaning within a regex, rather than representing themselves literally. Here are some of the most important metacharacters:
.
: Matches any character (except newline).^
: Matches the beginning of the string.$
: Matches the end of the string.*
: Matches zero or more occurrences of the preceding character.+
: Matches one or more occurrences of the preceding character.?
: Matches zero or one occurrence of the preceding character.[]
: Defines a character set. For example,[abc]
matches ‘a’, ‘b’, or ‘c’.()
: Creates a capturing group.\|
: Acts as an “or” operator. For example,cat|dog
matches either “cat” or “dog”.\
: Escapes a metacharacter, allowing you to match it literally.
Character Classes
Character classes provide shorthand for common character sets:
\d
: Matches any digit (0-9).\D
: Matches any non-digit character.\w
: Matches any alphanumeric character (a-z, A-Z, 0-9, and underscore).\W
: Matches any non-alphanumeric character.\s
: Matches any whitespace character (space, tab, newline).\S
: Matches any non-whitespace character.
Quantifiers
Quantifiers specify how many times a character or group should appear:
{n}
: Matches exactly n occurrences.{n,}
: Matches n or more occurrences.{n,m}
: Matches between n and m occurrences.
Example: Extracting Email Addresses
Let’s illustrate how to use regular expressions to extract email addresses from a text:
1
2
3
4
5
6
7
import re
text = "Contact us at support@example.com or sales@example.co.uk for assistance."
pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" # a more robust email pattern
emails = re.findall(pattern, text)
print("Emails found:", emails)
This example uses a more sophisticated pattern to handle variations in email addresses. However, even this pattern is not perfect and might not catch all valid email addresses, as email address format can be complex.
Compiling Regular Expressions
For improved performance, especially when using the same regex multiple times, you can compile the regex using re.compile()
.
1
2
3
4
5
6
7
import re
compiled_pattern = re.compile(r"\b\d{3}-\d{3}-\d{4}\b") # phone number pattern
text = "My phone number is 555-123-4567 and another number is 123-456-7890."
matches = compiled_pattern.findall(text)
print(matches)
This improves efficiency by pre-compiling the pattern before using it.
Substitution and Replacement
The re.sub()
function allows you to replace parts of a string that match a pattern.
1
2
3
4
5
import re
text = "This is a test string."
new_text = re.sub(r"test", "sample", text)
print(new_text)
This tutorial has only scratched the surface of the capabilities of regular expressions. There’s much more to explore, including lookarounds, named capturing groups, and more advanced techniques. However, with this foundation, you should now be able to use regular expressions effectively to solve many common string manipulation problems in Python. Remember to consult the Python re
module documentation for further details and advanced usage. Practice is key – the more you experiment and work with regex, the more proficient you’ll become.