Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
106: Regex Syntax Fundamentals
I'll be honest with you: the first time I encountered regular expressions (regex), I thought someone was playing a prank on me. Looking at a string like ^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$ looks more like a cat walked across a keyboard than actual code. But once you realize that regex is just a specialized language for describing patterns, it becomes one of the most powerful tools in your kit.
Instead of lecturing you on a table of symbols, let's actually build something. Imagine we're processing a messy batch of order confirmation emails, and we need to pull out the Order ID and the total price from strings like this: "Order #A1234 confirmed for $99.50" and "Order #B5678 confirmed for $120.00".
Hunting for the Order ID
First, I need to identify what stays the same and what changes. The text "Order #" is constant, but the ID (like A1234) changes. In regex, we use \d for digits and [A-Z] for uppercase letters. Since our IDs start with a letter followed by numbers, I'll start there.
import re
text = "Order #A1234 confirmed for $99.50"
# I'll use [A-Z] for the first letter and \d+ for one or more digits
pattern = r"Order #[A-Z]\d+"
match = re.search(pattern, text)
print(match.group()) # Output: Order #A1234
Note that I used a "raw string" (the r before the quotes). Always do this with regex in Python. Without it, Python's own string escaping interferes with regex's escaping, and you'll end up in a debugging nightmare.
Taming the Special Characters
Now I want to grab the price. It's a dollar sign, some digits, a decimal point, and two more digits. Here is where I usually trip up when I'm rushing. Watch what happens when I try to write this pattern:
# My first (wrong) attempt
pattern = r"Order #[A-Z]\d+ confirmed for $\d+.\d+"
match = re.search(pattern, text)
If I ran this, I might get lucky, but I've made a classic mistake. In regex, the dot . is a wildcard—it matches any character except a newline. If my text was "Order #A1234 confirmed for $99x50", that pattern would still match it because the dot doesn't mean "literal period" here; it means "anything".
To fix this, I have to "escape" the dot with a backslash \. to tell regex, "No, I actually mean a period." Also, the dollar sign $ is a special character that usually signifies the end of a string. I need to escape that too.
# The corrected version
pattern = r"Order #[A-Z]\d+ confirmed for \$\d+\.\d+"
match = re.search(pattern, text)
print(match.group()) # Output: Order #A1234 confirmed for $99.50
Isolating the Data with Groups
Right now, match.group() gives me the whole sentence. That's useless if I just want the ID and the price for a database. This is where capture groups—the parentheses ()—come in. Anything inside parentheses is "captured" as a separate piece of data.
I'll wrap the ID part and the price part in parentheses. I'll also leave the "Order #" and "confirmed for" outside the groups because they are just landmarks to help regex find the right spot.
# Creating two capture groups
pattern = r"Order #([A-Z]\d+) confirmed for \$(\d+\.\d+)"
match = re.search(pattern, text)
if match:
order_id = match.group(1)
price = match.group(2)
print(f"ID: {order_id}, Price: {price}")
# Output: ID: A1234, Price: 99.50
Now we've gone from a messy string to structured data. We used \d+ for "one or more digits", \. to escape a special character, and () to slice out the specific bits we actually care about.
📋 Practical Task
Extracting Flight Itinerary Details
You've been handed a list of flight confirmation strings from a travel agency. Your task is to write a regex pattern that extracts the Flight Number and the Date from the strings.
The format is always: "Flight [Two uppercase letters][3 digits] departs on [YYYY-MM-DD]"
Example Input: "Flight AA123 departs on 2023-12-25"
Expected Output: Flight: AA123, Date: 2023-12-25
Write a Python script using the re module that uses capture groups to isolate the flight number and the date, then print them in the expected format.
There are no comments for now.