# ==============================================================================
# JUNIOR PYTHON TRACK 29 — REGULAR EXPRESSIONS (re)
# ==============================================================================
import re
# 1. Matching & Searching (`re.search` vs `re.match`)
log_line = "2026-09-20 20:50:00 [ERROR] User 404 failed login attempt from 192.168.1.5"
# re.search scans string for first location matching pattern
ip_match = re.search(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", log_line)
ip_address = ip_match.group() if ip_match else "Not found"
# 2. Capturing Groups & Named Groups (`re.search` with groups)
log_pattern = r"(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(?P<level>\w+)\] (?P<msg>.*)"
parsed_log = re.search(log_pattern, log_line)
if parsed_log:
log_dict = parsed_log.groupdict()
# log_dict -> {'timestamp': '2026-09-20 20:50:00', 'level': 'ERROR', 'msg': 'User 404 failed...'}
# 3. Find All & Substitution (`re.findall` & `re.sub`)
text = "Contact support at dev@example.com or admin@teachcloud.org for help."
emails = re.findall(r"[\w\.-]+@[\w\.-]+\.\w+", text)
# Redact emails for privacy
redacted_text = re.sub(r"[\w\.-]+@[\w\.-]+\.\w+", "[REDACTED_EMAIL]", text)
# 4. Strict Validation Function
def validate_username(username: str) -> bool:
"""Usernames must be 3-16 chars, lowercase alphanumeric, underscore or hyphen."""
pattern = r"^[a-z0-9_-]{3,16}$"
return bool(re.match(pattern, username))
# 💡 GOLDEN RULE: Don't use regex when simpler Python string methods work!
def is_csv_file(filename: str) -> bool:
# ❌ BAD: re.search(r'\.csv$', filename)
# ✅ GOOD: Simpler, faster, cleaner
return filename.endswith(".csv")
if __name__ == "__main__":
print("=== 1. IP Search Result ===")
print(f"Extracted IP: {ip_address}")
print("\n=== 2. Log Line Groups ===")
print(f"Log Level: {parsed_log.group('level') if parsed_log else 'N/A'}")
print("\n=== 3. Extracted Emails ===")
print(emails)
print("\n=== 4. Redacted Text ===")
print(redacted_text)
print("\n=== 5. Username Validation ===")
print(f"'shkar_dev' valid: {validate_username('shkar_dev')}")
print("'Invalid User!' valid: {validate_username('Invalid User!')}")
$ python3 regex_studio.py
=== 1. IP Search Result ===
Extracted IP: 192.168.1.5
=== 2. Log Line Groups ===
Log Level: ERROR
=== 3. Extracted Emails ===
['dev@example.com', 'admin@teachcloud.org']
=== 4. Redacted Text ===
Contact support at [REDACTED_EMAIL] or [REDACTED_EMAIL] for help.
=== 5. Username Validation ===
'shkar_dev' valid: True
'Invalid User!' valid: False
Execution completed successfully.
import unittest
import re
class TestJuniorRegex(unittest.TestCase):
def test_re_search_and_groups(self):
pattern = r"(\d{3})-(\d{3}-\d{4})"
match = re.search(pattern, "Call 555-867-5309 today")
self.assertIsNotNone(match)
self.assertEqual(match.group(1), "555")
self.assertEqual(match.group(2), "867-5309")
def test_character_classes_and_findall(self):
digits = re.findall(r"\d+", "Items: 12 apples, 45 oranges, 99 bananas")
self.assertEqual(digits, ["12", "45", "99"])
def test_regex_substitution(self):
clean_str = re.sub(r"\s+", " ", "Multiple spaces here")
self.assertEqual(clean_str, "Multiple spaces here")
def test_validation_anchors(self):
pattern = r"^\d{5}$" # 5-digit US ZIP code
self.assertTrue(bool(re.match(pattern, "90210")))
self.assertFalse(bool(re.match(pattern, "902101")))
if __name__ == "__main__":
unittest.main()