Real applications need to validate user input, extract data from logs, and parse structured text. This page provides ready-to-use regex patterns for common tasks: email validation, phone number formatting, URL extraction, and data parsing. These patterns serve as building blocks for text processing pipelines.

Regular expression patterns are reusable solutions for common text matching tasks. This page covers practical patterns for email, phone, URL validation, and text extraction.

Email Patterns

test_email
email.py
Replay: real traced execution (multi-file project)
# Email validation patterns

import re

# Email patterns
# Basic email pattern
basic_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"

emails = [
    "user@example.com",
    "first.last@domain.co.uk",
    "user+tag@example.org",
    "invalid@",
    "@invalid.com",
    "no-at-sign.com",
    "user@domain",
    "user@domain.c"
]

print("Basic email validation:")
pattern = re.compile(basic_email)
for email in emails:
    valid = bool(pattern.match(email))
    print(f"  {email}: {valid}")

# Extract email parts
email_pattern = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"
extract_pattern = re.compile(email_pattern)

print("\nExtract email parts:")
test_email = "john.doe@example.com"
match = extract_pattern.match(test_email)

if match:
    print(f"  Email: {test_email}")
    print(f"  Username: {match.group(1)}")
    print(f"  Domain: {match.group(2)}")
    print(f"  TLD: {match.group(3)}")

# Find all emails in text
text = """
Contact us at support@example.com or sales@company.org.
For urgent matters, email admin@service.net immediately.
"""

find_pattern = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
found_emails = find_pattern.findall(text)

print("\nEmails found in text:")
for email in found_emails:
    print(f"  {email}")

# More strict pattern (requires valid TLD length)
strict_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"
strict_pattern = re.compile(strict_email)

print("\nStrict validation:")
test_emails = [
    "user@domain.com",
    "user@domain.co",
    "user@domain.technology"  # 10 chars TLD
]

for email in test_emails:
    valid = bool(strict_pattern.match(email))
    print(f"  {email}: {valid}")

# Named groups
named_pattern = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"
named_re = re.compile(named_pattern)

match2 = named_re.match("alice@example.com")
if match2:
    print("\nNamed groups:")
    print(f"  Username: {match2.group('username')}")
    print(f"  Domain: {match2.group('domain')}")
    print(f"  TLD: {match2.group('tld')}")

# Email validation patterns

import re

# Email patterns
# Basic email pattern
basic_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"

emails = [
    "user@example.com",
    "first.last@domain.co.uk",
    "user+tag@example.org",
    "invalid@",
    "@invalid.com",
    "no-at-sign.com",
    "user@domain",
    "user@domain.c"
]

print("Basic email validation:")
pattern = re.compile(basic_email)
for email in emails:
    valid = bool(pattern.match(email))
    print(f"  {email}: {valid}")

# Extract email parts
email_pattern = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"
extract_pattern = re.compile(email_pattern)

print("\nExtract email parts:")
test_email = "admin@service.net"
match = extract_pattern.match(test_email)

if match:
    print(f"  Email: {test_email}")
    print(f"  Username: {match.group(1)}")
    print(f"  Domain: {match.group(2)}")
    print(f"  TLD: {match.group(3)}")

# Find all emails in text
text = """
Contact us at support@example.com or sales@company.org.
For urgent matters, email admin@service.net immediately.
"""

find_pattern = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
found_emails = find_pattern.findall(text)

print("\nEmails found in text:")
for email in found_emails:
    print(f"  {email}")

# More strict pattern (requires valid TLD length)
strict_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"
strict_pattern = re.compile(strict_email)

print("\nStrict validation:")
test_emails = [
    "user@domain.com",
    "user@domain.co",
    "user@domain.technology"  # 10 chars TLD
]

for email in test_emails:
    valid = bool(strict_pattern.match(email))
    print(f"  {email}: {valid}")

# Named groups
named_pattern = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"
named_re = re.compile(named_pattern)

match2 = named_re.match("alice@example.com")
if match2:
    print("\nNamed groups:")
    print(f"  Username: {match2.group('username')}")
    print(f"  Domain: {match2.group('domain')}")
    print(f"  TLD: {match2.group('tld')}")

# Email validation patterns

import re

# Email patterns
# Basic email pattern
basic_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"

emails = [
    "user@example.com",
    "first.last@domain.co.uk",
    "user+tag@example.org",
    "invalid@",
    "@invalid.com",
    "no-at-sign.com",
    "user@domain",
    "user@domain.c"
]

print("Basic email validation:")
pattern = re.compile(basic_email)
for email in emails:
    valid = bool(pattern.match(email))
    print(f"  {email}: {valid}")

# Extract email parts
email_pattern = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"
extract_pattern = re.compile(email_pattern)

print("\nExtract email parts:")
test_email = "invalid@"
match = extract_pattern.match(test_email)

if match:
    print(f"  Email: {test_email}")
    print(f"  Username: {match.group(1)}")
    print(f"  Domain: {match.group(2)}")
    print(f"  TLD: {match.group(3)}")

# Find all emails in text
text = """
Contact us at support@example.com or sales@company.org.
For urgent matters, email admin@service.net immediately.
"""

find_pattern = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")
found_emails = find_pattern.findall(text)

print("\nEmails found in text:")
for email in found_emails:
    print(f"  {email}")

# More strict pattern (requires valid TLD length)
strict_email = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"
strict_pattern = re.compile(strict_email)

print("\nStrict validation:")
test_emails = [
    "user@domain.com",
    "user@domain.co",
    "user@domain.technology"  # 10 chars TLD
]

for email in test_emails:
    valid = bool(strict_pattern.match(email))
    print(f"  {email}: {valid}")

# Named groups
named_pattern = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"
named_re = re.compile(named_pattern)

match2 = named_re.match("alice@example.com")
if match2:
    print("\nNamed groups:")
    print(f"  Username: {match2.group('username')}")
    print(f"  Domain: {match2.group('domain')}")
    print(f"  TLD: {match2.group('tld')}")

  1. basic_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

    6# Basic email pattern7basic_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"89emails→ ['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c'] = [10    "user@example.com",11    "first.last@domain.co.uk",12    "user+tag@example.org",13    "invalid@",14    "@invalid.com",15    "no-at-sign.com",16    "user@domain",17    "user@domain.c"18]1920print("Basic email validation:")21pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(basic_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)22for email in emails:
    outputBasic email validation:
  2. valid ← True

    pass 1 of 8
    21pattern = re.compile(basic_email)22for emailuser@example.com in emails['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c']:23    valid→ True = bool(patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$').match(emailuser@example.com))24    print(f"  {emailuser@example.com}: {validTrue}")
    output  user@example.com: True
    All 8 passes — pass 1 is the card above
    passemailvalid
    1user@example.comTrue
    2first.last@domain.co.ukTrue
    3user+tag@example.orgTrue
    4invalid@False
    5@invalid.comFalse
    6no-at-sign.comFalse
    7user@domainFalse
    8user@domain.cFalse
  3. email_pattern ← ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$

    26# Extract email parts27email_pattern→ ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$ = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"28extract_pattern→ re.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(email_pattern^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$)2930print("\nExtract email parts:")31test_email→ john.doe@example.com = "john.doe@example.com"32#@test_email="admin@service.net", "invalid@"33match→ <re.Match object; span=(0, 20), match='john.doe@example.com'> = extract_patternre.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$').match(test_emailjohn.doe@example.com)
    output
    Extract email parts:
  4. if match:

    35if match<re.Match object; span=(0, 20), match='john.doe@example.com'>:36    print(f"  Email: {test_emailjohn.doe@example.com}")37    print(f"  Username: {match<re.Match object; span=(0, 20), match='john.doe@example.com'>.group(1)}")38    print(f"  Domain: {match<re.Match object; span=(0, 20), match='john.doe@example.com'>.group(2)}")39    print(f"  TLD: {match<re.Match object; span=(0, 20), match='john.doe@example.com'>.group(3)}")
    output  Email: john.doe@example.com
      Username: john.doe
      Domain: example
      TLD: com
  5. text ← Contact us at support@example.com or sales@company.org. For urgent matters, email admin@service.net immediately.

    41# Find all emails in text42text→
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
     = """43Contact us at support@example.com or sales@company.org.44For urgent matters, email admin@service.net immediately.45"""4647find_pattern→ re.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")48found_emails→ ['support@example.com', 'sales@company.org', 'admin@service.net'] = find_patternre.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}').findall(text
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
    )4950print("\nEmails found in text:")51for email in found_emails:
    output
    Emails found in text:
  6. for email in found_emails:

    pass 1 of 3
    50print("\nEmails found in text:")51for emailsupport@example.com in found_emails['support@example.com', 'sales@company.org', 'admin@service.net']:52    print(f"  {emailsupport@example.com}")
    output  support@example.com
    All 3 passes — pass 1 is the card above
    passemail
    1support@example.com
    2sales@company.org
    3admin@service.net
  7. strict_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$

    54# More strict pattern (requires valid TLD length)55strict_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"56strict_pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(strict_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$)5758print("\nStrict validation:")59test_emails→ ['user@domain.com', 'user@domain.co', 'user@domain.technology'] = [60    "user@domain.com",61    "user@domain.co",62    "user@domain.technology"  # 10 chars TLD63]
    output
    Strict validation:
  8. valid ← True

    pass 1 of 3
    65for emailuser@domain.com in test_emails['user@domain.com', 'user@domain.co', 'user@domain.technology']:66    valid→ True = bool(strict_patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$').match(emailuser@domain.com))67    print(f"  {emailuser@domain.com}: {validTrue}")
    output  user@domain.com: True
    All 3 passes — pass 1 is the card above
    passemailvalid
    1user@domain.comTrue
    2user@domain.coTrue
    3user@domain.technologyFalse
  9. named_pattern ← ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$

    69# Named groups70named_pattern→ ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$ = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"71named_re→ re.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(named_pattern^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$)7273match2→ <re.Match object; span=(0, 17), match='alice@example.com'> = named_rere.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$').match("alice@example.com")74if match2:
  10. if match2:

    73match2 = named_re.match("alice@example.com")74if match2<re.Match object; span=(0, 17), match='alice@example.com'>:75    print("\nNamed groups:")76    print(f"  Username: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('username')}")77    print(f"  Domain: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('domain')}")78    print(f"  TLD: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('tld')}")
    output
    Named groups:
      Username: alice
      Domain: example
      TLD: com
  1. basic_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

    6# Basic email pattern7basic_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"89emails→ ['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c'] = [10    "user@example.com",11    "first.last@domain.co.uk",12    "user+tag@example.org",13    "invalid@",14    "@invalid.com",15    "no-at-sign.com",16    "user@domain",17    "user@domain.c"18]1920print("Basic email validation:")21pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(basic_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)22for email in emails:
    outputBasic email validation:
  2. valid ← True

    pass 1 of 8
    21pattern = re.compile(basic_email)22for emailuser@example.com in emails['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c']:23    valid→ True = bool(patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$').match(emailuser@example.com))24    print(f"  {emailuser@example.com}: {validTrue}")
    output  user@example.com: True
    All 8 passes — pass 1 is the card above
    passemailvalid
    1user@example.comTrue
    2first.last@domain.co.ukTrue
    3user+tag@example.orgTrue
    4invalid@False
    5@invalid.comFalse
    6no-at-sign.comFalse
    7user@domainFalse
    8user@domain.cFalse
  3. email_pattern ← ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$

    26# Extract email parts27email_pattern→ ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$ = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"28extract_pattern→ re.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(email_pattern^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$)2930print("\nExtract email parts:")31test_email→ admin@service.net = "admin@service.net"32match→ <re.Match object; span=(0, 17), match='admin@service.net'> = extract_patternre.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$').match(test_emailadmin@service.net)
    output
    Extract email parts:
  4. if match:

    34if match<re.Match object; span=(0, 17), match='admin@service.net'>:35    print(f"  Email: {test_emailadmin@service.net}")36    print(f"  Username: {match<re.Match object; span=(0, 17), match='admin@service.net'>.group(1)}")37    print(f"  Domain: {match<re.Match object; span=(0, 17), match='admin@service.net'>.group(2)}")38    print(f"  TLD: {match<re.Match object; span=(0, 17), match='admin@service.net'>.group(3)}")
    output  Email: admin@service.net
      Username: admin
      Domain: service
      TLD: net
  5. text ← Contact us at support@example.com or sales@company.org. For urgent matters, email admin@service.net immediately.

    40# Find all emails in text41text→
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
     = """42Contact us at support@example.com or sales@company.org.43For urgent matters, email admin@service.net immediately.44"""4546find_pattern→ re.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")47found_emails→ ['support@example.com', 'sales@company.org', 'admin@service.net'] = find_patternre.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}').findall(text
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
    )4849print("\nEmails found in text:")50for email in found_emails:
    output
    Emails found in text:
  6. for email in found_emails:

    pass 1 of 3
    49print("\nEmails found in text:")50for emailsupport@example.com in found_emails['support@example.com', 'sales@company.org', 'admin@service.net']:51    print(f"  {emailsupport@example.com}")
    output  support@example.com
    All 3 passes — pass 1 is the card above
    passemail
    1support@example.com
    2sales@company.org
    3admin@service.net
  7. strict_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$

    53# More strict pattern (requires valid TLD length)54strict_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"55strict_pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(strict_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$)5657print("\nStrict validation:")58test_emails→ ['user@domain.com', 'user@domain.co', 'user@domain.technology'] = [59    "user@domain.com",60    "user@domain.co",61    "user@domain.technology"  # 10 chars TLD62]
    output
    Strict validation:
  8. valid ← True

    pass 1 of 3
    64for emailuser@domain.com in test_emails['user@domain.com', 'user@domain.co', 'user@domain.technology']:65    valid→ True = bool(strict_patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$').match(emailuser@domain.com))66    print(f"  {emailuser@domain.com}: {validTrue}")
    output  user@domain.com: True
    All 3 passes — pass 1 is the card above
    passemailvalid
    1user@domain.comTrue
    2user@domain.coTrue
    3user@domain.technologyFalse
  9. named_pattern ← ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$

    68# Named groups69named_pattern→ ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$ = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"70named_re→ re.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(named_pattern^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$)7172match2→ <re.Match object; span=(0, 17), match='alice@example.com'> = named_rere.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$').match("alice@example.com")73if match2:
  10. if match2:

    72match2 = named_re.match("alice@example.com")73if match2<re.Match object; span=(0, 17), match='alice@example.com'>:74    print("\nNamed groups:")75    print(f"  Username: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('username')}")76    print(f"  Domain: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('domain')}")77    print(f"  TLD: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('tld')}")
    output
    Named groups:
      Username: alice
      Domain: example
      TLD: com
  1. basic_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

    6# Basic email pattern7basic_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"89emails→ ['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c'] = [10    "user@example.com",11    "first.last@domain.co.uk",12    "user+tag@example.org",13    "invalid@",14    "@invalid.com",15    "no-at-sign.com",16    "user@domain",17    "user@domain.c"18]1920print("Basic email validation:")21pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(basic_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)22for email in emails:
    outputBasic email validation:
  2. valid ← True

    pass 1 of 8
    21pattern = re.compile(basic_email)22for emailuser@example.com in emails['user@example.com', 'first.last@domain.co.uk', 'user+tag@example.org', 'invalid@', '@invalid.com', 'no-at-sign.com', 'user@domain', 'user@domain.c']:23    valid→ True = bool(patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$').match(emailuser@example.com))24    print(f"  {emailuser@example.com}: {validTrue}")
    output  user@example.com: True
    All 8 passes — pass 1 is the card above
    passemailvalid
    1user@example.comTrue
    2first.last@domain.co.ukTrue
    3user+tag@example.orgTrue
    4invalid@False
    5@invalid.comFalse
    6no-at-sign.comFalse
    7user@domainFalse
    8user@domain.cFalse
  3. email_pattern ← ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$

    26# Extract email parts27email_pattern→ ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$ = r"^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$"28extract_pattern→ re.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(email_pattern^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$)2930print("\nExtract email parts:")31test_email→ invalid@ = "invalid@"32match→ None = extract_patternre.compile('^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\\.([a-zA-Z]{2,})$').match(test_emailinvalid@)3334if match:35    print(f"  Email: {test_email}")36    print(f"  Username: {match.group(1)}")37    print(f"  Domain: {match.group(2)}")38    print(f"  TLD: {match.group(3)}")3940# Find all emails in text41text→
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
     = """42Contact us at support@example.com or sales@company.org.43For urgent matters, email admin@service.net immediately.44"""4546find_pattern→ re.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")47found_emails→ ['support@example.com', 'sales@company.org', 'admin@service.net'] = find_patternre.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}').findall(text
    Contact us at support@example.com or sales@company.org.
    For urgent matters, email admin@service.net immediately.
    )4849print("\nEmails found in text:")50for email in found_emails:
    output
    Extract email parts:
    
    Emails found in text:
  4. for email in found_emails:

    pass 1 of 3
    49print("\nEmails found in text:")50for emailsupport@example.com in found_emails['support@example.com', 'sales@company.org', 'admin@service.net']:51    print(f"  {emailsupport@example.com}")
    output  support@example.com
    All 3 passes — pass 1 is the card above
    passemail
    1support@example.com
    2sales@company.org
    3admin@service.net
  5. strict_email ← ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$

    53# More strict pattern (requires valid TLD length)54strict_email→ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$ = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$"55strict_pattern→ re.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(strict_email^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$)5657print("\nStrict validation:")58test_emails→ ['user@domain.com', 'user@domain.co', 'user@domain.technology'] = [59    "user@domain.com",60    "user@domain.co",61    "user@domain.technology"  # 10 chars TLD62]
    output
    Strict validation:
  6. valid ← True

    pass 1 of 3
    64for emailuser@domain.com in test_emails['user@domain.com', 'user@domain.co', 'user@domain.technology']:65    valid→ True = bool(strict_patternre.compile('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$').match(emailuser@domain.com))66    print(f"  {emailuser@domain.com}: {validTrue}")
    output  user@domain.com: True
    All 3 passes — pass 1 is the card above
    passemailvalid
    1user@domain.comTrue
    2user@domain.coTrue
    3user@domain.technologyFalse
  7. named_pattern ← ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$

    68# Named groups69named_pattern→ ^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$ = r"^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$"70named_re→ re.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(named_pattern^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\.(?P<tld>[a-zA-Z]{2,})$)7172match2→ <re.Match object; span=(0, 17), match='alice@example.com'> = named_rere.compile('^(?P<username>[a-zA-Z0-9._%+-]+)@(?P<domain>[a-zA-Z0-9.-]+)\\.(?P<tld>[a-zA-Z]{2,})$').match("alice@example.com")73if match2:
  8. if match2:

    72match2 = named_re.match("alice@example.com")73if match2<re.Match object; span=(0, 17), match='alice@example.com'>:74    print("\nNamed groups:")75    print(f"  Username: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('username')}")76    print(f"  Domain: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('domain')}")77    print(f"  TLD: {match2<re.Match object; span=(0, 17), match='alice@example.com'>.group('tld')}")
    output
    Named groups:
      Username: alice
      Domain: example
      TLD: com
email_pattern Pattern for validating and extracting email addresses

Phone Patterns

phone.py
Replay: real traced execution (multi-file project)
# Phone number patterns

import re

# Phone patterns
# US phone formats
patterns = [
    r"\(\d{3}\)\s\d{3}-\d{4}",  # (123) 456-7890
    r"\d{3}-\d{3}-\d{4}",        # 123-456-7890
    r"\d{10}"                    # 1234567890
]

phones = [
    "(555) 123-4567",
    "555-123-4567",
    "5551234567",
    "(555)123-4567",  # no space
    "555.123.4567",
    "invalid"
]

print("Phone validation:")
for i, pattern_str in enumerate(patterns, 1):
    print(f"\nPattern {i}:")
    p = re.compile(pattern_str)
    for phone in phones:
        valid = bool(p.fullmatch(phone))
        print(f"  {phone}: {valid}")

# Combined pattern (any format)
any_format = r"^(\(\d{3}\)\s?|\d{3}-)?\d{3}-?\d{4}$"
any_pattern = re.compile(any_format)

print("\nCombined pattern:")
for phone in phones:
    valid = bool(any_pattern.match(phone))
    print(f"  {phone}: {valid}")

# Extract phone parts
extract_pattern = r"\((\d{3})\)\s(\d{3})-(\d{4})"
extract = re.compile(extract_pattern)

test_phone = "(555) 123-4567"
match = extract.match(test_phone)

if match:
    print(f"\nExtracted parts from {test_phone}:")
    print(f"  Area code: {match.group(1)}")
    print(f"  Exchange: {match.group(2)}")
    print(f"  Number: {match.group(3)}")

# Find all phones in text
text = """
Call us at (555) 123-4567 or 555-987-6543.
Emergency: (999) 911-0000
"""

find_pattern = re.compile(r"\(?\d{3}\)?[-\s]?\d{3}-\d{4}")
found = find_pattern.findall(text)

print("\nPhones found in text:")
for phone in found:
    print(f"  {phone}")

# International format (basic)
intl_pattern = r"^\+?\d{1,3}[-\s]?\(?\d{1,4}\)?[-\s]?\d{1,4}[-\s]?\d{1,9}$"
intl_p = re.compile(intl_pattern)

intl_phones = [
    "+1 (555) 123-4567",
    "+44 20 7123 4567",
    "+81 3-1234-5678"
]

print("\nInternational phones:")
for phone in intl_phones:
    valid = bool(intl_p.match(phone))
    print(f"  {phone}: {valid}")

# Format phone number
def format_phone(digits):
    """Convert 10 digits to (XXX) XXX-XXXX format"""
    if len(digits) == 10 and digits.isdigit():
        return f"({digits[:3]}) {digits[3:6]}-{digits[6:]}"
    return None

print("\nFormat phone:")
raw = "5551234567"
formatted = format_phone(raw)
print(f"  {raw} -> {formatted}")

  1. patterns ← ['\\(\\d{3}\\)\\s\\d{3}-\\d{4}', '\\d{3}-\\d{3}-\\d{4}', '\\d{10}']

    6# US phone formats7patterns→ ['\\(\\d{3}\\)\\s\\d{3}-\\d{4}', '\\d{3}-\\d{3}-\\d{4}', '\\d{10}'] = [8    r"\(\d{3}\)\s\d{3}-\d{4}",  # (123) 456-78909    r"\d{3}-\d{3}-\d{4}",        # 123-456-789010    r"\d{10}"                    # 123456789011]1213phones→ ['(555) 123-4567', '555-123-4567', '5551234567', '(555)123-4567', '555.123.4567', 'invalid'] = [14    "(555) 123-4567",15    "555-123-4567",16    "5551234567",17    "(555)123-4567",  # no space18    "555.123.4567",19    "invalid"20]2122print("Phone validation:")23for i, pattern_str in enumerate(patterns, 1):
    outputPhone validation:
  2. p ← re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')

    pass 1 of 3
    22print("Phone validation:")23for i1, pattern_str\(\d{3}\)\s\d{3}-\d{4} in enumerate(patterns['\\(\\d{3}\\)\\s\\d{3}-\\d{4}', '\\d{3}-\\d{3}-\\d{4}', '\\d{10}'], 1):24    print(f"\nPattern {i1}:")25    p→ re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(pattern_str\(\d{3}\)\s\d{3}-\d{4})26    for phone in phones:
    output
    Pattern 1:
    All 3 passes — pass 1 is the card above
    passipattern_strp
    11\(\d{3}\)\s\d{3}-\d{4}re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')
    22\d{3}-\d{3}-\d{4}re.compile('\\d{3}-\\d{3}-\\d{4}')
    33\d{10}re.compile('\\d{10}')
  3. valid ← True

    pass 1 of 18
    25p = re.compile(pattern_str)26for phone(555) 123-4567 in phones['(555) 123-4567', '555-123-4567', '5551234567', '(555)123-4567', '555.123.4567', 'invalid']:27    valid→ True = bool(pre.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}').fullmatch(phone(555) 123-4567))28    print(f"  {phone(555) 123-4567}: {validTrue}")
    output  (555) 123-4567: True
    18 passes — pass 1 is the card above
    passphonepvalid
    1(555) 123-4567re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')True
    2555-123-4567re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')False
    35551234567re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')False
    4(555)123-4567re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')False
    5555.123.4567re.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')False
    6invalidre.compile('\\(\\d{3}\\)\\s\\d{3}-\\d{4}')False
    7(555) 123-4567re.compile('\\d{3}-\\d{3}-\\d{4}')False
    8555-123-4567re.compile('\\d{3}-\\d{3}-\\d{4}')True
    95551234567re.compile('\\d{3}-\\d{3}-\\d{4}')False
    ⋯ 7 more passes ⋯
    17555.123.4567re.compile('\\d{10}')False
    18invalidre.compile('\\d{10}')False
  4. any_format ← ^(\(\d{3}\)\s?|\d{3}-)?\d{3}-?\d{4}$, any_pattern ← re.compile('^(\\(\\d{3}\\)\\s?|\\d{3}-)?\\d{3}-?\\d{4}$')

    30# Combined pattern (any format)31any_format→ ^(\(\d{3}\)\s?|\d{3}-)?\d{3}-?\d{4}$ = r"^(\(\d{3}\)\s?|\d{3}-)?\d{3}-?\d{4}$"32any_pattern→ re.compile('^(\\(\\d{3}\\)\\s?|\\d{3}-)?\\d{3}-?\\d{4}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(any_format^(\(\d{3}\)\s?|\d{3}-)?\d{3}-?\d{4}$)3334print("\nCombined pattern:")35for phone in phones:
    output
    Combined pattern:
  5. valid ← True

    pass 1 of 6
    34print("\nCombined pattern:")35for phone(555) 123-4567 in phones['(555) 123-4567', '555-123-4567', '5551234567', '(555)123-4567', '555.123.4567', 'invalid']:36    valid→ True = bool(any_patternre.compile('^(\\(\\d{3}\\)\\s?|\\d{3}-)?\\d{3}-?\\d{4}$').match(phone(555) 123-4567))37    print(f"  {phone(555) 123-4567}: {validTrue}")
    output  (555) 123-4567: True
    All 6 passes — pass 1 is the card above
    passphonevalid
    1(555) 123-4567True
    2555-123-4567True
    35551234567False
    4(555)123-4567True
    5555.123.4567False
    6invalidFalse
  6. extract_pattern ← \((\d{3})\)\s(\d{3})-(\d{4}), extract ← re.compile('\\((\\d{3})\\)\\s(\\d{3})-(\\d{4})')

    39# Extract phone parts40extract_pattern→ \((\d{3})\)\s(\d{3})-(\d{4}) = r"\((\d{3})\)\s(\d{3})-(\d{4})"41extract→ re.compile('\\((\\d{3})\\)\\s(\\d{3})-(\\d{4})') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(extract_pattern\((\d{3})\)\s(\d{3})-(\d{4}))4243test_phone→ (555) 123-4567 = "(555) 123-4567"44match→ <re.Match object; span=(0, 14), match='(555) 123-4567'> = extractre.compile('\\((\\d{3})\\)\\s(\\d{3})-(\\d{4})').match(test_phone(555) 123-4567)
  7. if match:

    46if match<re.Match object; span=(0, 14), match='(555) 123-4567'>:47    print(f"\nExtracted parts from {test_phone(555) 123-4567}:")48    print(f"  Area code: {match<re.Match object; span=(0, 14), match='(555) 123-4567'>.group(1)}")49    print(f"  Exchange: {match<re.Match object; span=(0, 14), match='(555) 123-4567'>.group(2)}")50    print(f"  Number: {match<re.Match object; span=(0, 14), match='(555) 123-4567'>.group(3)}")
    output
    Extracted parts from (555) 123-4567:
      Area code: 555
      Exchange: 123
      Number: 4567
  8. text ← Call us at (555) 123-4567 or 555-987-6543. Emergency: (999) 911-0000

    52# Find all phones in text53text→
    Call us at (555) 123-4567 or 555-987-6543.
    Emergency: (999) 911-0000
     = """54Call us at (555) 123-4567 or 555-987-6543.55Emergency: (999) 911-000056"""5758find_pattern→ re.compile('\\(?\\d{3}\\)?[-\\s]?\\d{3}-\\d{4}') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"\(?\d{3}\)?[-\s]?\d{3}-\d{4}")59found→ ['(555) 123-4567', '555-987-6543', '(999) 911-0000'] = find_patternre.compile('\\(?\\d{3}\\)?[-\\s]?\\d{3}-\\d{4}').findall(text
    Call us at (555) 123-4567 or 555-987-6543.
    Emergency: (999) 911-0000
    )6061print("\nPhones found in text:")62for phone in found:
    output
    Phones found in text:
  9. for phone in found:

    pass 1 of 3
    61print("\nPhones found in text:")62for phone(555) 123-4567 in found['(555) 123-4567', '555-987-6543', '(999) 911-0000']:63    print(f"  {phone(555) 123-4567}")
    output  (555) 123-4567
    All 3 passes — pass 1 is the card above
    passphone
    1(555) 123-4567
    2555-987-6543
    3(999) 911-0000
  10. intl_pattern ← ^\+?\d{1,3}[-\s]?\(?\d{1,4}\)?[-\s]?\d{1,4}[-\s]?\d{1,9}$

    65# International format (basic)66intl_pattern→ ^\+?\d{1,3}[-\s]?\(?\d{1,4}\)?[-\s]?\d{1,4}[-\s]?\d{1,9}$ = r"^\+?\d{1,3}[-\s]?\(?\d{1,4}\)?[-\s]?\d{1,4}[-\s]?\d{1,9}$"67intl_p→ re.compile('^\\+?\\d{1,3}[-\\s]?\\(?\\d{1,4}\\)?[-\\s]?\\d{1,4}[-\\s]?\\d{1,9}$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(intl_pattern^\+?\d{1,3}[-\s]?\(?\d{1,4}\)?[-\s]?\d{1,4}[-\s]?\d{1,9}$)6869intl_phones→ ['+1 (555) 123-4567', '+44 20 7123 4567', '+81 3-1234-5678'] = [70    "+1 (555) 123-4567",71    "+44 20 7123 4567",72    "+81 3-1234-5678"73]7475print("\nInternational phones:")76for phone in intl_phones:
    output
    International phones:
  11. valid ← True

    pass 1 of 3
    75print("\nInternational phones:")76for phone+1 (555) 123-4567 in intl_phones['+1 (555) 123-4567', '+44 20 7123 4567', '+81 3-1234-5678']:77    valid→ True = bool(intl_pre.compile('^\\+?\\d{1,3}[-\\s]?\\(?\\d{1,4}\\)?[-\\s]?\\d{1,4}[-\\s]?\\d{1,9}$').match(phone+1 (555) 123-4567))78    print(f"  {phone+1 (555) 123-4567}: {validTrue}")
    output  +1 (555) 123-4567: True
    All 3 passes — pass 1 is the card above
    passphonevalid
    1+1 (555) 123-4567True
    2+44 20 7123 4567True
    3+81 3-1234-5678True
  12. raw ← 5551234567

    87print("\nFormat phone:")88raw→ 5551234567 = "5551234567"89formatted = format_phone(raw5551234567)90print(f"  {raw} -> {formatted}")
    output
    Format phone:
  13. def format_phone(digits):

    80# Format phone number81def format_phone(digits5551234567):82    """Convert 10 digits to (XXX) XXX-XXXX format"""83    if len(digits) == 10 and digits.isdigit():
  14. if len(digits) == 10 and digits.isdigit():

    82"""Convert 10 digits to (XXX) XXX-XXXX format"""83if len(digits5551234567) == 10 and digits.isdigit():84    return f"({digits[:3]555}) {digits[3:6]123}-{digits[6:]4567}"85return None
  15. formatted ← (555) 123-4567

    88raw = "5551234567"89formatted→ (555) 123-4567 = format_phone(raw5551234567)90print(f"  {raw5551234567} -> {formatted(555) 123-4567}")
    output  5551234567 -> (555) 123-4567
phone_pattern Patterns for various phone number formats including international

URL Patterns

url.py
Replay: real traced execution (multi-file project)
# URL patterns

import re

# URL patterns
# Basic URL pattern
url_pattern = r"^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$"

urls = [
    "https://example.com",
    "http://www.example.com",
    "https://sub.example.co.uk",
    "https://example.com/path",
    "https://example.com/path?key=value",
    "ftp://example.com",  # wrong protocol
    "example.com",        # missing protocol
    "https://localhost"   # no TLD
]

print("URL validation:")
pattern = re.compile(url_pattern)
for url in urls:
    valid = bool(pattern.match(url))
    print(f"  {url}: {valid}")

# Extract URL parts
extract_pattern = r"^(https?)://([a-zA-Z0-9.-]+)(/.*)? $"
extract_p = re.compile(extract_pattern)

test_url = "https://www.example.com/path/to/page"
match = extract_p.match(test_url)

if match:
    print(f"\nExtracted parts from {test_url}:")
    print(f"  Protocol: {match.group(1)}")
    print(f"  Domain: {match.group(2)}")
    print(f"  Path: {match.group(3) if match.group(3) else '/'}")

# More detailed extraction
detail_pattern = r"^(https?)://([^:/]+)(?::(\d+))?(/.*)?$"
detail_p = re.compile(detail_pattern)

test_urls = [
    "https://example.com:8080/path",
    "http://localhost:3000/api",
    "https://example.com/page"
]

print("\nDetailed URL parsing:")
for url in test_urls:
    m = detail_p.match(url)
    if m:
        print(f"  {url}")
        print(f"    Protocol: {m.group(1)}")
        print(f"    Host: {m.group(2)}")
        print(f"    Port: {m.group(3) if m.group(3) else 'default'}")
        print(f"    Path: {m.group(4) if m.group(4) else '/'}")

# Find all URLs in text
text = """
Visit https://example.com for more info.
Check out http://test.org/page and https://another.site/path?q=search
"""

find_pattern = re.compile(r"https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}[^\s]*")
found = find_pattern.findall(text)

print("\nURLs found in text:")
for url in found:
    print(f"  {url}")

# Query parameters
query_pattern = r"[?&]([^=]+)=([^&]+)"
url_with_query = "https://example.com/search?q=regex&lang=python&page=1"

query_p = re.compile(query_pattern)
params = query_p.findall(url_with_query)

print(f"\nQuery parameters from: {url_with_query}")
for key, value in params:
    print(f"  {key} = {value}")

# Named groups for URL parsing
named_pattern = r"^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/.*)?$"
named_p = re.compile(named_pattern)

match2 = named_p.match("https://example.com:8080/api/v1")
if match2:
    print("\nNamed groups:")
    print(f"  Protocol: {match2.group('protocol')}")
    print(f"  Domain: {match2.group('domain')}")
    print(f"  Port: {match2.group('port')}")
    print(f"  Path: {match2.group('path')}")

  1. url_pattern ← ^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$, urls ← ['https://example.com', 'http://www.example.com', 'https://sub.example.co.uk', 'https://example.com/path', 'https://example.com/path?key=value', 'ftp://example.com', 'example.com', 'https://localhost']

    6# Basic URL pattern7url_pattern→ ^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$ = r"^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$"89urls→ ['https://example.com', 'http://www.example.com', 'https://sub.example.co.uk', 'https://example.com/path', 'https://example.com/path?key=value', 'ftp://example.com', 'example.com', 'https://localhost'] = [10    "https://example.com",11    "http://www.example.com",12    "https://sub.example.co.uk",13    "https://example.com/path",14    "https://example.com/path?key=value",15    "ftp://example.com",  # wrong protocol16    "example.com",        # missing protocol17    "https://localhost"   # no TLD18]1920print("URL validation:")21pattern→ re.compile('^https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}.*$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(url_pattern^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$)22for url in urls:
    outputURL validation:
  2. valid ← True

    pass 1 of 8
    21pattern = re.compile(url_pattern)22for urlhttps://example.com in urls['https://example.com', 'http://www.example.com', 'https://sub.example.co.uk', 'https://example.com/path', 'https://example.com/path?key=value', 'ftp://example.com', 'example.com', 'https://localhost']:23    valid→ True = bool(patternre.compile('^https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}.*$').match(urlhttps://example.com))24    print(f"  {urlhttps://example.com}: {validTrue}")
    output  https://example.com: True
    All 8 passes — pass 1 is the card above
    passurlvalid
    1https://example.comTrue
    2http://www.example.comTrue
    3https://sub.example.co.ukTrue
    4https://example.com/pathTrue
    5https://example.com/path?key=valueTrue
    6ftp://example.comFalse
    7example.comFalse
    8https://localhostFalse
  3. extract_pattern ← ^(https?)://([a-zA-Z0-9.-]+)(/.*)? $, extract_p ← re.compile('^(https?)://([a-zA-Z0-9.-]+)(/.*)? $')

    26# Extract URL parts27extract_pattern→ ^(https?)://([a-zA-Z0-9.-]+)(/.*)? $ = r"^(https?)://([a-zA-Z0-9.-]+)(/.*)? $"28extract_p→ re.compile('^(https?)://([a-zA-Z0-9.-]+)(/.*)? $') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(extract_pattern^(https?)://([a-zA-Z0-9.-]+)(/.*)? $)2930test_url→ https://www.example.com/path/to/page = "https://www.example.com/path/to/page"31match→ None = extract_pre.compile('^(https?)://([a-zA-Z0-9.-]+)(/.*)? $').match(test_urlhttps://www.example.com/path/to/page)3233if match:34    print(f"\nExtracted parts from {test_url}:")35    print(f"  Protocol: {match.group(1)}")36    print(f"  Domain: {match.group(2)}")37    print(f"  Path: {match.group(3) if match.group(3) else '/'}")3839# More detailed extraction40detail_pattern→ ^(https?)://([^:/]+)(?::(\d+))?(/.*)?$ = r"^(https?)://([^:/]+)(?::(\d+))?(/.*)?$"41detail_p→ re.compile('^(https?)://([^:/]+)(?::(\\d+))?(/.*)?$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(detail_pattern^(https?)://([^:/]+)(?::(\d+))?(/.*)?$)4243test_urls→ ['https://example.com:8080/path', 'http://localhost:3000/api', 'https://example.com/page'] = [44    "https://example.com:8080/path",45    "http://localhost:3000/api",46    "https://example.com/page"47]4849print("\nDetailed URL parsing:")50for url in test_urls:
    output
    Detailed URL parsing:
  4. m ← <re.Match object; span=(0, 29), match='https://example.com:8080/path'>

    pass 1 of 3
    49print("\nDetailed URL parsing:")50for urlhttps://example.com:8080/path in test_urls['https://example.com:8080/path', 'http://localhost:3000/api', 'https://example.com/page']:51    m→ <re.Match object; span=(0, 29), match='https://example.com:8080/path'> = detail_pre.compile('^(https?)://([^:/]+)(?::(\\d+))?(/.*)?$').match(urlhttps://example.com:8080/path)52    if m:
    All 3 passes — pass 1 is the card above
    passurlm
    1https://example.com:8080/path<re.Match object; span=(0, 29), match='https://example.com:8080/path'>
    2http://localhost:3000/api<re.Match object; span=(0, 25), match='http://localhost:3000/api'>
    3https://example.com/page<re.Match object; span=(0, 24), match='https://example.com/page'>
  5. if m:

    pass 1 of 3
    51m = detail_p.match(url)52if m<re.Match object; span=(0, 29), match='https://example.com:8080/path'>:53    print(f"  {urlhttps://example.com:8080/path}")54    print(f"    Protocol: {m<re.Match object; span=(0, 29), match='https://example.com:8080/path'>.group(1)}")55    print(f"    Host: {m<re.Match object; span=(0, 29), match='https://example.com:8080/path'>.group(2)}")56    print(f"    Port: {m<re.Match object; span=(0, 29), match='https://example.com:8080/path'>.group(3) if m.group(3) else 'default'}")57    print(f"    Path: {m<re.Match object; span=(0, 29), match='https://example.com:8080/path'>.group(4) if m.group(4) else '/'}")
    output  https://example.com:8080/path
        Protocol: https
        Host: example.com
        Port: 8080
        Path: /path
    All 3 passes — pass 1 is the card above
    passmurl
    1<re.Match object; span=(0, 29), match='https://example.com:8080/path'>https://example.com:8080/path
    2<re.Match object; span=(0, 25), match='http://localhost:3000/api'>http://localhost:3000/api
    3<re.Match object; span=(0, 24), match='https://example.com/page'>https://example.com/page
  6. text ← Visit https://example.com for more info. Check out http://test.org/page and https://another.site/path?q=search

    59# Find all URLs in text60text→
    Visit https://example.com for more info.
    Check out http://test.org/page and https://another.site/path?q=search
     = """61Visit https://example.com for more info.62Check out http://test.org/page and https://another.site/path?q=search63"""6465find_pattern→ re.compile('https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}[^\\s]*') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}[^\s]*")66found→ ['https://example.com', 'http://test.org/page', 'https://another.site/path?q=search'] = find_patternre.compile('https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}[^\\s]*').findall(text
    Visit https://example.com for more info.
    Check out http://test.org/page and https://another.site/path?q=search
    )6768print("\nURLs found in text:")69for url in found:
    output
    URLs found in text:
  7. for url in found:

    pass 1 of 3
    68print("\nURLs found in text:")69for urlhttps://example.com in found['https://example.com', 'http://test.org/page', 'https://another.site/path?q=search']:70    print(f"  {urlhttps://example.com}")
    output  https://example.com
    All 3 passes — pass 1 is the card above
    passurl
    1https://example.com
    2http://test.org/page
    3https://another.site/path?q=search
  8. query_pattern ← [?&]([^=]+)=([^&]+), url_with_query ← https://example.com/search?q=regex&lang=python&page=1

    72# Query parameters73query_pattern→ [?&]([^=]+)=([^&]+) = r"[?&]([^=]+)=([^&]+)"74url_with_query→ https://example.com/search?q=regex&lang=python&page=1 = "https://example.com/search?q=regex&lang=python&page=1"7576query_p→ re.compile('[?&]([^=]+)=([^&]+)') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(query_pattern[?&]([^=]+)=([^&]+))77params→ [('q', 'regex'), ('lang', 'python'), ('page', '1')] = query_pre.compile('[?&]([^=]+)=([^&]+)').findall(url_with_queryhttps://example.com/search?q=regex&lang=python&page=1)7879print(f"\nQuery parameters from: {url_with_queryhttps://example.com/search?q=regex&lang=python&page=1}")80for key, value in params:
    output
    Query parameters from: https://example.com/search?q=regex&lang=python&page=1
  9. for key, value in params:

    pass 1 of 3
    79print(f"\nQuery parameters from: {url_with_query}")80for keyq, valueregex in params[('q', 'regex'), ('lang', 'python'), ('page', '1')]:81    print(f"  {keyq} = {valueregex}")
    output  q = regex
    All 3 passes — pass 1 is the card above
    passkeyvalue
    1qregex
    2langpython
    3page1
  10. named_pattern ← ^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/.*)?$

    83# Named groups for URL parsing84named_pattern→ ^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/.*)?$ = r"^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/.*)?$"85named_p→ re.compile('^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\\d+))?(?P<path>/.*)?$') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(named_pattern^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/.*)?$)8687match2→ <re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'> = named_pre.compile('^(?P<protocol>https?)://(?P<domain>[^:/]+)(?::(?P<port>\\d+))?(?P<path>/.*)?$').match("https://example.com:8080/api/v1")88if match2:
  11. if match2:

    87match2 = named_p.match("https://example.com:8080/api/v1")88if match2<re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'>:89    print("\nNamed groups:")90    print(f"  Protocol: {match2<re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'>.group('protocol')}")91    print(f"  Domain: {match2<re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'>.group('domain')}")92    print(f"  Port: {match2<re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'>.group('port')}")93    print(f"  Path: {match2<re.Match object; span=(0, 31), match='https://example.com:8080/api/v1'>.group('path')}")
    output
    Named groups:
      Protocol: https
      Domain: example.com
      Port: 8080
      Path: /api/v1
url_pattern Pattern for matching web URLs with http/https

Text Extraction

extraction.py
Replay: real traced execution (multi-file project)
# Text extraction with regex

import re

# Extract hashtags
def extract_hashtags(text):
    """Extract all hashtags from text"""
    return re.findall(r"#\w+", text)

# Extract mentions
def extract_mentions(text):
    """Extract all @mentions from text"""
    return re.findall(r"@\w+", text)

# Extract numbers
def extract_numbers(text):
    """Extract all numbers (including decimals and negatives)"""
    matches = re.findall(r"-?\d+\.?\d*", text)
    return [float(m) for m in matches if m and m != '-']

# Extract dates
def extract_dates(text):
    """Extract dates in YYYY-MM-DD format"""
    return re.findall(r"\d{4}-\d{2}-\d{2}", text)

# Main test
if __name__ == "__main__":
    # Social media text
    tweet = """
    Loving #python and #regex! Thanks @copilot for the help.
    Check out #programming tips at https://example.com
    Mentions: @user1 @user2 #coding
    """

    print("Social media extraction:")
    print(f"Hashtags: {extract_hashtags(tweet)}")
    print(f"Mentions: {extract_mentions(tweet)}")

    # Numbers
    data_text = "Prices: $19.99, $5.50, and $100. Temperature: -5.5°C"
    print("\nNumbers extraction:")
    print(f"Numbers: {extract_numbers(data_text)}")

    # Dates
    log_text = """
    2025-01-29: Error occurred
    2025-01-30: Fixed bug
    2025-02-01: Deployed
    """
    print("\nDates extraction:")
    print(f"Dates: {extract_dates(log_text)}")

    # IP addresses
    server_log = "Requests from 192.168.1.1, 10.0.0.5, and 172.16.0.10"
    ips = re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", server_log)
    print("\nIP addresses:")
    for ip in ips:
        print(f"  {ip}")

    # Extract quoted strings
    quote_text = 'He said "Hello" and she replied "Hi there!"'
    quotes = re.findall(r'"([^"]+)"', quote_text)
    print("\nQuoted strings:")
    for quote in quotes:
        print(f"  {quote}")

    # Key-value pairs
    config = "name=John age=30 city=NYC email=john@example.com"
    kv_pairs = re.findall(r"(\w+)=(\S+)", config)
    print("\nKey-value pairs:")
    for key, value in kv_pairs:
        print(f"  {key} = {value}")

    # HTML tags (simple)
    html = "<div>Content</div><span>Text</span>"
    # Using backreference \1 to match closing tag
    tags = re.findall(r"<(\w+)>([^<]+)</\1>", html)
    print("\nHTML content:")
    for tag, content in tags:
        print(f"  <{tag}>: {content}")

    # Email addresses
    text_with_emails = "Contact alice@example.com or bob@test.org for info"
    emails = re.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text_with_emails)
    print("\nEmail addresses:")
    for email in emails:
        print(f"  {email}")

    # Extract words
    sentence = "The quick-brown fox jumps over the lazy dog."
    words = re.findall(r"\b\w+\b", sentence)
    print(f"\nWords: {words}")

    # Extract capitalized words
    caps = re.findall(r"\b[A-Z]\w*\b", "Python, Java, and JavaScript are Languages")
    print(f"Capitalized words: {caps}")

  1. tweet ← Loving #python and #regex! Thanks @copilot for the help. Check out #programming tips at https://example.com Mentions: @user1 @user2 #coding

    26# Main test27if __name__ == "__main__":28    # Social media text29    tweet→
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
         = """30    Loving #python and #regex! Thanks @copilot for the help.31    Check out #programming tips at https://example.com32    Mentions: @user1 @user2 #coding33    """3435    print("Social media extraction:")36    print(f"Hashtags: {extract_hashtags(tweet
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )}")37    print(f"Mentions: {extract_mentions(tweet)}")
    outputSocial media extraction:
  2. def extract_hashtags(text):

    5# Extract hashtags6def extract_hashtags(text
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        ):7    """Extract all hashtags from text"""8    return re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"#\w+", text
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )
  3. print(f"Hashtags: {extract_hashtags(tweet)}")

    35print("Social media extraction:")36print(f"Hashtags: {extract_hashtags(tweet
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )}")37print(f"Mentions: {extract_mentions(tweet
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )}")
    outputHashtags: ['#python', '#regex', '#programming', '#coding']
  4. def extract_mentions(text):

    10# Extract mentions11def extract_mentions(text
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        ):12    """Extract all @mentions from text"""13    return re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"@\w+", text
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )
  5. data_text ← Prices: $19.99, $5.50, and $100. Temperature: -5.5°C

    36print(f"Hashtags: {extract_hashtags(tweet)}")37print(f"Mentions: {extract_mentions(tweet
        Loving #python and #regex! Thanks @copilot for the help.
        Check out #programming tips at https://example.com
        Mentions: @user1 @user2 #coding
        )}")3839# Numbers40data_text→ Prices: $19.99, $5.50, and $100. Temperature: -5.5°C = "Prices: $19.99, $5.50, and $100. Temperature: -5.5°C"41print("\nNumbers extraction:")42print(f"Numbers: {extract_numbers(data_textPrices: $19.99, $5.50, and $100. Temperature: -5.5°C)}")
    outputMentions: ['@copilot', '@user1', '@user2']
    
    Numbers extraction:
  6. matches ← ['19.99', '5.50', '100.', '-5.5']

    15# Extract numbers16def extract_numbers(textPrices: $19.99, $5.50, and $100. Temperature: -5.5°C):17    """Extract all numbers (including decimals and negatives)"""18    matches→ ['19.99', '5.50', '100.', '-5.5'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"-?\d+\.?\d*", textPrices: $19.99, $5.50, and $100. Temperature: -5.5°C)19    return [float(m) for m in matches['19.99', '5.50', '100.', '-5.5'] if m and m != '-']
  7. log_text ← 2025-01-29: Error occurred 2025-01-30: Fixed bug 2025-02-01: Deployed

    41print("\nNumbers extraction:")42print(f"Numbers: {extract_numbers(data_textPrices: $19.99, $5.50, and $100. Temperature: -5.5°C)}")4344# Dates45log_text→
        2025-01-29: Error occurred
        2025-01-30: Fixed bug
        2025-02-01: Deployed
         = """462025-01-29: Error occurred472025-01-30: Fixed bug482025-02-01: Deployed49"""50print("\nDates extraction:")51print(f"Dates: {extract_dates(log_text
        2025-01-29: Error occurred
        2025-01-30: Fixed bug
        2025-02-01: Deployed
        )}")
    outputNumbers: [19.99, 5.5, 100.0, -5.5]
    
    Dates extraction:
  8. def extract_dates(text):

    21# Extract dates22def extract_dates(text
        2025-01-29: Error occurred
        2025-01-30: Fixed bug
        2025-02-01: Deployed
        ):23    """Extract dates in YYYY-MM-DD format"""24    return re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"\d{4}-\d{2}-\d{2}", text
        2025-01-29: Error occurred
        2025-01-30: Fixed bug
        2025-02-01: Deployed
        )
  9. server_log ← Requests from 192.168.1.1, 10.0.0.5, and 172.16.0.10

    50print("\nDates extraction:")51print(f"Dates: {extract_dates(log_text
        2025-01-29: Error occurred
        2025-01-30: Fixed bug
        2025-02-01: Deployed
        )}")5253# IP addresses54server_log→ Requests from 192.168.1.1, 10.0.0.5, and 172.16.0.10 = "Requests from 192.168.1.1, 10.0.0.5, and 172.16.0.10"55ips→ ['192.168.1.1', '10.0.0.5', '172.16.0.10'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", server_logRequests from 192.168.1.1, 10.0.0.5, and 172.16.0.10)56print("\nIP addresses:")57for ip in ips:
    outputDates: ['2025-01-29', '2025-01-30', '2025-02-01']
    
    IP addresses:
  10. for ip in ips:

    pass 1 of 3
    56print("\nIP addresses:")57for ip192.168.1.1 in ips['192.168.1.1', '10.0.0.5', '172.16.0.10']:58    print(f"  {ip192.168.1.1}")
    output  192.168.1.1
    All 3 passes — pass 1 is the card above
    passip
    1192.168.1.1
    210.0.0.5
    3172.16.0.10
  11. quote_text ← He said "Hello" and she replied "Hi there!", quotes ← ['Hello', 'Hi there!']

    60# Extract quoted strings61quote_text→ He said "Hello" and she replied "Hi there!" = 'He said "Hello" and she replied "Hi there!"'62quotes→ ['Hello', 'Hi there!'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r'"([^"]+)"', quote_textHe said "Hello" and she replied "Hi there!")63print("\nQuoted strings:")64for quote in quotes:
    output
    Quoted strings:
  12. for quote in quotes:

    pass 1 of 2
    63print("\nQuoted strings:")64for quoteHello in quotes['Hello', 'Hi there!']:65    print(f"  {quoteHello}")
    output  Hello
  13. for quote in quotes:

    pass 2 of 2
    63print("\nQuoted strings:")64for quoteHi there! in quotes['Hello', 'Hi there!']:65    print(f"  {quoteHi there!}")
    output  Hi there!
  14. config ← name=John age=30 city=NYC email=john@example.com, kv_pairs ← [('name', 'John'), ('age', '30'), ('city', 'NYC'), ('email', 'john@example.com')]

    67# Key-value pairs68config→ name=John age=30 city=NYC email=john@example.com = "name=John age=30 city=NYC email=john@example.com"69kv_pairs→ [('name', 'John'), ('age', '30'), ('city', 'NYC'), ('email', 'john@example.com')] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"(\w+)=(\S+)", configname=John age=30 city=NYC email=john@example.com)70print("\nKey-value pairs:")71for key, value in kv_pairs:
    output
    Key-value pairs:
  15. for key, value in kv_pairs:

    pass 1 of 4
    70print("\nKey-value pairs:")71for keyname, valueJohn in kv_pairs[('name', 'John'), ('age', '30'), ('city', 'NYC'), ('email', 'john@example.com')]:72    print(f"  {keyname} = {valueJohn}")
    output  name = John
    All 4 passes — pass 1 is the card above
    passkeyvalue
    1nameJohn
    2age30
    3cityNYC
    4emailjohn@example.com
  16. html ← <div>Content</div><span>Text</span>, tags ← [('div', 'Content'), ('span', 'Text')]

    74# HTML tags (simple)75html→ <div>Content</div><span>Text</span> = "<div>Content</div><span>Text</span>"76# Using backreference \1 to match closing tag77tags→ [('div', 'Content'), ('span', 'Text')] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"<(\w+)>([^<]+)</\1>", html<div>Content</div><span>Text</span>)78print("\nHTML content:")79for tag, content in tags:
    output
    HTML content:
  17. for tag, content in tags:

    pass 1 of 2
    78print("\nHTML content:")79for tagdiv, contentContent in tags[('div', 'Content'), ('span', 'Text')]:80    print(f"  <{tagdiv}>: {contentContent}")
    output  <div>: Content
  18. for tag, content in tags:

    pass 2 of 2
    78print("\nHTML content:")79for tagspan, contentText in tags[('div', 'Content'), ('span', 'Text')]:80    print(f"  <{tagspan}>: {contentText}")
    output  <span>: Text
  19. text_with_emails ← Contact alice@example.com or bob@test.org for info

    82# Email addresses83text_with_emails→ Contact alice@example.com or bob@test.org for info = "Contact alice@example.com or bob@test.org for info"84emails→ ['alice@example.com', 'bob@test.org'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text_with_emailsContact alice@example.com or bob@test.org for info)85print("\nEmail addresses:")86for email in emails:
    output
    Email addresses:
  20. for email in emails:

    pass 1 of 2
    85print("\nEmail addresses:")86for emailalice@example.com in emails['alice@example.com', 'bob@test.org']:87    print(f"  {emailalice@example.com}")
    output  alice@example.com
  21. for email in emails:

    pass 2 of 2
    85print("\nEmail addresses:")86for emailbob@test.org in emails['alice@example.com', 'bob@test.org']:87    print(f"  {emailbob@test.org}")
    output  bob@test.org
  22. sentence ← The quick-brown fox jumps over the lazy dog., words ← ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']

    89# Extract words90sentence→ The quick-brown fox jumps over the lazy dog. = "The quick-brown fox jumps over the lazy dog."91words→ ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"\b\w+\b", sentenceThe quick-brown fox jumps over the lazy dog.)92print(f"\nWords: {words['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']}")9394# Extract capitalized words95caps→ ['Python', 'Java', 'JavaScript', 'Languages'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.findall(r"\b[A-Z]\w*\b", "Python, Java, and JavaScript are Languages")96print(f"Capitalized words: {caps['Python', 'Java', 'JavaScript', 'Languages']}")
    output
    Words: ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']
    Capitalized words: ['Python', 'Java', 'JavaScript', 'Languages']
text_extraction Extracting hashtags, mentions, numbers, and dates from text

Replacement Operations

replacement.py
Replay: real traced execution (multi-file project)
# String replacement with regex

import re

# Basic replacement
# Simple sub
text1 = "Hello World, Hello Python"
result1 = re.sub(r"Hello", "Hi", text1)
print(f"Original: {text1}")
print(f"Replaced: {result1}")

# Replace with pattern
text2 = "Call 555-1234 or 555-5678"
result2 = re.sub(r"\d{3}-\d{4}", "XXX-XXXX", text2)
print("\nMask phone numbers:")
print(f"Original: {text2}")
print(f"Masked: {result2}")

# Replace with groups
text3 = "2025-01-29"
result3 = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\2/\3/\1", text3)
print("\nReformat date:")
print(f"Original (YYYY-MM-DD): {text3}")
print(f"Reformatted (MM/DD/YYYY): {result3}")

# Remove extra whitespace
text4 = "Too    many     spaces"
result4 = re.sub(r"\s+", " ", text4)
print("\nNormalize whitespace:")
print(f"Original: '{text4}'")
print(f"Normalized: '{result4}'")

# Remove HTML tags
html = "<p>Hello <b>World</b></p>"
result5 = re.sub(r"<[^>]+>", "", html)
print("\nRemove HTML:")
print(f"Original: {html}")
print(f"Clean: {result5}")

# Censor profanity (example)
text6 = "This is bad and terrible"
result6 = re.sub(r"\b(bad|terrible)\b", "***", text6)
print("\nCensor words:")
print(f"Original: {text6}")
print(f"Censored: {result6}")

# Format currency
text7 = "Price: 1234.56"
result7 = re.sub(r"(\d+)", r"$\1", text7)
print("\nAdd currency:")
print(f"Original: {text7}")
print(f"Formatted: {result7}")

# Replacement with function
def uppercase_match(match):
    """Convert matched word to uppercase"""
    return match.group(0).upper()

text8 = "one two three"
result8 = re.sub(r"\w+", uppercase_match, text8)
print("\nCustom replacement (function):")
print(f"Original: {text8}")
print(f"Uppercase: {result8}")

# Advanced: swap first and last name
names = "John Doe, Jane Smith, Bob Johnson"
result9 = re.sub(r"(\w+)\s(\w+)", r"\2, \1", names)
print("\nSwap names:")
print(f"Original: {names}")
print(f"Swapped: {result9}")

# Count replacements
text10 = "apple apple banana apple"
result10, count = re.subn(r"apple", "orange", text10)
print(f"\nReplace with count:")
print(f"Original: {text10}")
print(f"Replaced: {result10}")
print(f"Replacements: {count}")

# Replace only first N occurrences
text11 = "a a a a a"
result11 = re.sub(r"a", "b", text11, count=3)
print(f"\nReplace first 3:")
print(f"Original: {text11}")
print(f"Result: {result11}")

# Named groups in replacement
text12 = "John Doe"
pattern = r"(?P<first>\w+)\s(?P<last>\w+)"
result12 = re.sub(pattern, r"\g<last>, \g<first>", text12)
print(f"\nNamed group replacement:")
print(f"Original: {text12}")
print(f"Result: {result12}")

  1. text1 ← Hello World, Hello Python, result1 ← Hi World, Hi Python

    6# Simple sub7text1→ Hello World, Hello Python = "Hello World, Hello Python"8result1→ Hi World, Hi Python = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"Hello", "Hi", text1Hello World, Hello Python)9print(f"Original: {text1Hello World, Hello Python}")10print(f"Replaced: {result1Hi World, Hi Python}")1112# Replace with pattern13text2→ Call 555-1234 or 555-5678 = "Call 555-1234 or 555-5678"14result2→ Call XXX-XXXX or XXX-XXXX = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"\d{3}-\d{4}", "XXX-XXXX", text2Call 555-1234 or 555-5678)15print("\nMask phone numbers:")16print(f"Original: {text2Call 555-1234 or 555-5678}")17print(f"Masked: {result2Call XXX-XXXX or XXX-XXXX}")1819# Replace with groups20text3→ 2025-01-29 = "2025-01-29"21result3→ 01/29/2025 = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\2/\3/\1", text32025-01-29)22print("\nReformat date:")23print(f"Original (YYYY-MM-DD): {text32025-01-29}")24print(f"Reformatted (MM/DD/YYYY): {result301/29/2025}")2526# Remove extra whitespace27text4→ Too    many     spaces = "Too    many     spaces"28result4→ Too many spaces = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"\s+", " ", text4Too    many     spaces)29print("\nNormalize whitespace:")30print(f"Original: '{text4Too    many     spaces}'")31print(f"Normalized: '{result4Too many spaces}'")3233# Remove HTML tags34html→ <p>Hello <b>World</b></p> = "<p>Hello <b>World</b></p>"35result5→ Hello World = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"<[^>]+>", "", html<p>Hello <b>World</b></p>)36print("\nRemove HTML:")37print(f"Original: {html<p>Hello <b>World</b></p>}")38print(f"Clean: {result5Hello World}")3940# Censor profanity (example)41text6→ This is bad and terrible = "This is bad and terrible"42result6→ This is *** and *** = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"\b(bad|terrible)\b", "***", text6This is bad and terrible)43print("\nCensor words:")44print(f"Original: {text6This is bad and terrible}")45print(f"Censored: {result6This is *** and ***}")4647# Format currency48text7→ Price: 1234.56 = "Price: 1234.56"49result7→ Price: $1234.$56 = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"(\d+)", r"$\1", text7Price: 1234.56)50print("\nAdd currency:")51print(f"Original: {text7Price: 1234.56}")52print(f"Formatted: {result7Price: $1234.$56}")5354# Replacement with function55def uppercase_match(match):56    """Convert matched word to uppercase"""57    return match.group(0).upper()5859text8→ one two three = "one two three"60result8 = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"\w+", uppercase_match⟨function uppercase_match A⟩, text8one two three)61print("\nCustom replacement (function):")
    outputOriginal: Hello World, Hello Python
    Replaced: Hi World, Hi Python
    
    Mask phone numbers:
    Original: Call 555-1234 or 555-5678
    Masked: Call XXX-XXXX or XXX-XXXX
    
    Reformat date:
    Original (YYYY-MM-DD): 2025-01-29
    Reformatted (MM/DD/YYYY): 01/29/2025
    
    Normalize whitespace:
    Original: 'Too    many     spaces'
    Normalized: 'Too many spaces'
    
    Remove HTML:
    Original: <p>Hello <b>World</b></p>
    Clean: Hello World
    
    Censor words:
    Original: This is bad and terrible
    Censored: This is *** and ***
    
    Add currency:
    Original: Price: 1234.56
    Formatted: Price: $1234.$56
  2. def uppercase_match(match):

    pass 1 of 3
    54# Replacement with function55def uppercase_match(match<re.Match object; span=(0, 3), match='one'>):56    """Convert matched word to uppercase"""57    return match<re.Match object; span=(0, 3), match='one'>.group(0).upper()
    All 3 passes — pass 1 is the card above
    passmatch
    1<re.Match object; span=(0, 3), match='one'>
    2<re.Match object; span=(4, 7), match='two'>
    3<re.Match object; span=(8, 13), match='three'>
  3. result8 ← ONE TWO THREE, names ← John Doe, Jane Smith, Bob Johnson

    59text8 = "one two three"60result8→ ONE TWO THREE = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"\w+", uppercase_match⟨function uppercase_match A⟩, text8one two three)61print("\nCustom replacement (function):")62print(f"Original: {text8one two three}")63print(f"Uppercase: {result8ONE TWO THREE}")6465# Advanced: swap first and last name66names→ John Doe, Jane Smith, Bob Johnson = "John Doe, Jane Smith, Bob Johnson"67result9→ Doe, John, Smith, Jane, Johnson, Bob = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"(\w+)\s(\w+)", r"\2, \1", namesJohn Doe, Jane Smith, Bob Johnson)68print("\nSwap names:")69print(f"Original: {namesJohn Doe, Jane Smith, Bob Johnson}")70print(f"Swapped: {result9Doe, John, Smith, Jane, Johnson, Bob}")7172# Count replacements73text10→ apple apple banana apple = "apple apple banana apple"74result10→ orange orange banana orange, count→ 3 = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.subn(r"apple", "orange", text10apple apple banana apple)75print(f"\nReplace with count:")76print(f"Original: {text10apple apple banana apple}")77print(f"Replaced: {result10orange orange banana orange}")78print(f"Replacements: {count3}")7980# Replace only first N occurrences81text11→ a a a a a = "a a a a a"82result11→ b b b a a = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(r"a", "b", text11a a a a a, count=3)83print(f"\nReplace first 3:")84print(f"Original: {text11a a a a a}")85print(f"Result: {result11b b b a a}")8687# Named groups in replacement88text12→ John Doe = "John Doe"89pattern→ (?P<first>\w+)\s(?P<last>\w+) = r"(?P<first>\w+)\s(?P<last>\w+)"90result12→ Doe, John = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.sub(pattern(?P<first>\w+)\s(?P<last>\w+), r"\g<last>, \g<first>", text12John Doe)91print(f"\nNamed group replacement:")92print(f"Original: {text12John Doe}")93print(f"Result: {result12Doe, John}")
    output
    Custom replacement (function):
    Original: one two three
    Uppercase: ONE TWO THREE
    
    Swap names:
    Original: John Doe, Jane Smith, Bob Johnson
    Swapped: Doe, John, Smith, Jane, Johnson, Bob
    
    Replace with count:
    Original: apple apple banana apple
    Replaced: orange orange banana orange
    Replacements: 3
    
    Replace first 3:
    Original: a a a a a
    Result: b b b a a
    
    Named group replacement:
    Original: John Doe
    Result: Doe, John
regex_replacement Using re.sub() to transform text with patterns

Splitting with Patterns

splitting.py
Replay: real traced execution (multi-file project)
# String splitting with regex

import re

# Basic splitting
# Split by comma
csv1 = "apple,banana,cherry"
parts1 = csv1.split(",")
print("Split by comma:")
print(f"  {parts1}")

# Split by regex whitespace
text1 = "one two  three   four"
parts2 = re.split(r"\s+", text1)
print("\nSplit by whitespace:")
print(f"  {parts2}")

# Split by multiple delimiters
text2 = "apple;banana,cherry:orange"
parts3 = re.split(r"[;,:]+", text2)
print("\nSplit by multiple delimiters:")
print(f"  {parts3}")

# Split with limit (maxsplit)
text3 = "one,two,three,four,five"
parts4 = re.split(r",", text3, maxsplit=2)
print("\nSplit with maxsplit (2):")
print(f"  {parts4}")

# Split preserving delimiters (use groups)
text4 = "one,two;three"
parts5 = re.split(r"([,;])", text4)
print("\nSplit preserving delimiters:")
print(f"  {parts5}")

# Split by word boundaries
text5 = "hello-world_test"
parts6 = re.split(r"[-_]", text5)
print("\nSplit by hyphens and underscores:")
print(f"  {parts6}")

# Split sentences
paragraph = "First sentence. Second sentence! Third question?"
sentences = re.split(r"[.!?]\s*", paragraph)
print("\nSplit sentences:")
for i, sent in enumerate(sentences, 1):
    if sent:  # skip empty strings
        print(f"  {i}: {sent}")

# Split keeping empty strings
text6 = "a,,b,,,c"
parts7 = text6.split(",")  # regular split
parts8 = re.split(r",", text6)  # regex split
print("\nRegular split:")
print(f"  {parts7}")
print("Regex split (same behavior):")
print(f"  {parts8}")

# Split path
path = r"C:\Users\John\Documents\file.txt"
path_parts = re.split(r"\\", path)
print("\nSplit Windows path:")
print(f"  {path_parts}")

# Split by digits
text7 = "abc123def456ghi"
parts9 = re.split(r"\d+", text7)
print("\nSplit by digits:")
print(f"  {parts9}")

# Compiled pattern for reuse
pattern = re.compile(r"\s*,\s*")  # comma with optional spaces
text8 = "a, b,c ,d , e"
parts10 = pattern.split(text8)
print("\nSplit CSV with spaces:")
print(f"  {parts10}")

# Split complex: key=value pairs
config = "name=John;age=30;city=NYC"
pairs = config.split(";")
print("\nParse config:")
for pair in pairs:
    key, value = pair.split("=")
    print(f"  {key} -> {value}")

# Split with capturing groups
text9 = "a1b2c3"
parts11 = re.split(r"(\d)", text9)
print("\nSplit with captured delimiters:")
print(f"  {parts11}")

# Split by lookahead (keep delimiter)
text10 = "HelloWorld"
parts12 = re.split(r"(?=[A-Z])", text10)
print("\nSplit before capitals:")
print(f"  {parts12}")

# Split emails
emails = "alice@example.com, bob@test.org; charlie@demo.net"
email_list = re.split(r"[,;]\s*", emails)
print("\nSplit email list:")
for email in email_list:
    print(f"  {email}")

  1. csv1 ← apple,banana,cherry, parts1 ← ['apple', 'banana', 'cherry']

    6# Split by comma7csv1→ apple,banana,cherry = "apple,banana,cherry"8parts1→ ['apple', 'banana', 'cherry'] = csv1apple,banana,cherry.split(",")9print("Split by comma:")10print(f"  {parts1['apple', 'banana', 'cherry']}")1112# Split by regex whitespace13text1→ one two  three   four = "one two  three   four"14parts2→ ['one', 'two', 'three', 'four'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"\s+", text1one two  three   four)15print("\nSplit by whitespace:")16print(f"  {parts2['one', 'two', 'three', 'four']}")1718# Split by multiple delimiters19text2→ apple;banana,cherry:orange = "apple;banana,cherry:orange"20parts3→ ['apple', 'banana', 'cherry', 'orange'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"[;,:]+", text2apple;banana,cherry:orange)21print("\nSplit by multiple delimiters:")22print(f"  {parts3['apple', 'banana', 'cherry', 'orange']}")2324# Split with limit (maxsplit)25text3→ one,two,three,four,five = "one,two,three,four,five"26parts4→ ['one', 'two', 'three,four,five'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r",", text3one,two,three,four,five, maxsplit=2)27print("\nSplit with maxsplit (2):")28print(f"  {parts4['one', 'two', 'three,four,five']}")2930# Split preserving delimiters (use groups)31text4→ one,two;three = "one,two;three"32parts5→ ['one', ',', 'two', ';', 'three'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"([,;])", text4one,two;three)33print("\nSplit preserving delimiters:")34print(f"  {parts5['one', ',', 'two', ';', 'three']}")3536# Split by word boundaries37text5→ hello-world_test = "hello-world_test"38parts6→ ['hello', 'world', 'test'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"[-_]", text5hello-world_test)39print("\nSplit by hyphens and underscores:")40print(f"  {parts6['hello', 'world', 'test']}")4142# Split sentences43paragraph→ First sentence. Second sentence! Third question? = "First sentence. Second sentence! Third question?"44sentences→ ['First sentence', 'Second sentence', 'Third question', ''] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"[.!?]\s*", paragraphFirst sentence. Second sentence! Third question?)45print("\nSplit sentences:")46for i, sent in enumerate(sentences, 1):
    outputSplit by comma:
      ['apple', 'banana', 'cherry']
    
    Split by whitespace:
      ['one', 'two', 'three', 'four']
    
    Split by multiple delimiters:
      ['apple', 'banana', 'cherry', 'orange']
    
    Split with maxsplit (2):
      ['one', 'two', 'three,four,five']
    
    Split preserving delimiters:
      ['one', ',', 'two', ';', 'three']
    
    Split by hyphens and underscores:
      ['hello', 'world', 'test']
    
    Split sentences:
  2. for i, sent in enumerate(sentences, 1):

    pass 1 of 4
    45print("\nSplit sentences:")46for i1, sentFirst sentence in enumerate(sentences['First sentence', 'Second sentence', 'Third question', ''], 1):47    if sent:  # skip empty strings48        print(f"  {i}: {sent}")
    All 4 passes — pass 1 is the card above
    passisent
    11First sentence
    22Second sentence
    33Third question
    44(empty)
  3. if sent: # skip empty strings

    pass 1 of 3
    46for i, sent in enumerate(sentences, 1):47    if sentFirst sentence:  # skip empty strings48        print(f"  {i1}: {sentFirst sentence}")
    output  1: First sentence
    All 3 passes — pass 1 is the card above
    passsenti
    1First sentence1
    2Second sentence2
    3Third question3
  4. text6 ← a,,b,,,c, parts7 ← ['a', '', 'b', '', '', 'c'], parts8 ← ['a', '', 'b', '', '', 'c']

    50# Split keeping empty strings51text6→ a,,b,,,c = "a,,b,,,c"52parts7→ ['a', '', 'b', '', '', 'c'] = text6a,,b,,,c.split(",")  # regular split53parts8→ ['a', '', 'b', '', '', 'c'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r",", text6a,,b,,,c)  # regex split54print("\nRegular split:")55print(f"  {parts7['a', '', 'b', '', '', 'c']}")56print("Regex split (same behavior):")57print(f"  {parts8['a', '', 'b', '', '', 'c']}")5859# Split path60path→ C:\Users\John\Documents\file.txt = r"C:\Users\John\Documents\file.txt"61path_parts→ ['C:', 'Users', 'John', 'Documents', 'file.txt'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"\\", pathC:\Users\John\Documents\file.txt)62print("\nSplit Windows path:")63print(f"  {path_parts['C:', 'Users', 'John', 'Documents', 'file.txt']}")6465# Split by digits66text7→ abc123def456ghi = "abc123def456ghi"67parts9→ ['abc', 'def', 'ghi'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"\d+", text7abc123def456ghi)68print("\nSplit by digits:")69print(f"  {parts9['abc', 'def', 'ghi']}")7071# Compiled pattern for reuse72pattern→ re.compile('\\s*,\\s*') = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.compile(r"\s*,\s*")  # comma with optional spaces73text8→ a, b,c ,d , e = "a, b,c ,d , e"74parts10→ ['a', 'b', 'c', 'd', 'e'] = patternre.compile('\\s*,\\s*').split(text8a, b,c ,d , e)75print("\nSplit CSV with spaces:")76print(f"  {parts10['a', 'b', 'c', 'd', 'e']}")7778# Split complex: key=value pairs79config→ name=John;age=30;city=NYC = "name=John;age=30;city=NYC"80pairs→ ['name=John', 'age=30', 'city=NYC'] = configname=John;age=30;city=NYC.split(";")81print("\nParse config:")82for pair in pairs:
    output
    Regular split:
      ['a', '', 'b', '', '', 'c']
    Regex split (same behavior):
      ['a', '', 'b', '', '', 'c']
    
    Split Windows path:
      ['C:', 'Users', 'John', 'Documents', 'file.txt']
    
    Split by digits:
      ['abc', 'def', 'ghi']
    
    Split CSV with spaces:
      ['a', 'b', 'c', 'd', 'e']
    
    Parse config:
  5. key ← name, value ← John

    pass 1 of 3
    81print("\nParse config:")82for pairname=John in pairs['name=John', 'age=30', 'city=NYC']:83    key→ name, value→ John = pairname=John.split("=")84    print(f"  {keyname} -> {valueJohn}")
    output  name -> John
    All 3 passes — pass 1 is the card above
    passpairkeyvalue
    1name=JohnnameJohn
    2age=30age30
    3city=NYCcityNYC
  6. text9 ← a1b2c3, parts11 ← ['a', '1', 'b', '2', 'c', '3', ''], text10 ← HelloWorld

    86# Split with capturing groups87text9→ a1b2c3 = "a1b2c3"88parts11→ ['a', '1', 'b', '2', 'c', '3', ''] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"(\d)", text9a1b2c3)89print("\nSplit with captured delimiters:")90print(f"  {parts11['a', '1', 'b', '2', 'c', '3', '']}")9192# Split by lookahead (keep delimiter)93text10→ HelloWorld = "HelloWorld"94parts12→ ['', 'Hello', 'World'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"(?=[A-Z])", text10HelloWorld)95print("\nSplit before capitals:")96print(f"  {parts12['', 'Hello', 'World']}")9798# Split emails99emails→ alice@example.com, bob@test.org; charlie@demo.net = "alice@example.com, bob@test.org; charlie@demo.net"100email_list→ ['alice@example.com', 'bob@test.org', 'charlie@demo.net'] = re<module 're' from '/usr/local/lib/python3.12/re/__init__.py'>.split(r"[,;]\s*", emailsalice@example.com, bob@test.org; charlie@demo.net)101print("\nSplit email list:")102for email in email_list:
    output
    Split with captured delimiters:
      ['a', '1', 'b', '2', 'c', '3', '']
    
    Split before capitals:
      ['', 'Hello', 'World']
    
    Split email list:
  7. for email in email_list:

    pass 1 of 3
    101print("\nSplit email list:")102for emailalice@example.com in email_list['alice@example.com', 'bob@test.org', 'charlie@demo.net']:103    print(f"  {emailalice@example.com}")
    output  alice@example.com
    All 3 passes — pass 1 is the card above
    passemail
    1alice@example.com
    2bob@test.org
    3charlie@demo.net
regex_splitting Using re.split() to divide text on complex delimiters

Pattern Building Tips

  1. Start simple, add complexity
  2. Test with edge cases
  3. Use raw strings (r"...")
  4. Use groups for extraction
  5. Balance strictness vs flexibility

Exercise: extraction.py

Extract all emails, URLs, and hashtags from a sample social media post