Strings & regular expressions

Customer names, phone numbers, invoice IDs and addresses all arrive as text, and they are rarely clean. Python's string methods handle most cleaning jobs; regular expressions handle the rest.

Everyday string methods

Strings are immutable, so every method returns a new string.

raw = "  mumbai , MAHARASHTRA  "
city, state = [part.strip().title() for part in raw.split(",")]
print(city, state)                         # Mumbai Maharashtra

print("INV-2026-0042".startswith("INV"))   # True
print("9876543210".isdigit())              # True
print("-".join(["2026", "09", "22"]))      # 2026-09-22
print("Chai".center(10, "*"))              # ***Chai***

Formatting with f-strings

Format specifiers go after a colon inside the braces.

Spec Example Output
,.2f f"{1234567.5:,.2f}" 1,234,567.50
>8 f"{'Ok':>8}" Ok
% f"{0.183:.1%}" 18.3%
= (debug) f"{total=}" total=450

Note that , groups in thousands; Indian lakh/crore grouping needs custom code or the babel package.

Regular expressions with re

A regular expression is a mini-language for describing text patterns. Always write patterns as raw strings (r"...") so backslashes reach the regex engine untouched.

Pattern Matches
\d a digit
\w letter, digit or underscore
\s whitespace
+ / * / ? one or more / zero or more / optional
{10} exactly ten times
^ / $ start / end of string
( ) a capture group
import re

text = "Call Priya on 98765 43210 or Arjun at +91-9123456780."

# Remove spaces and dashes, then find 10-digit Indian mobile numbers
digits = re.sub(r"[\s-]", "", text)
print(re.findall(r"(?:\+91)?([6-9]\d{9})", digits))   # ['9876543210', '9123456780']

# Validate a GSTIN-like code: 2 digits, 5 letters, 4 digits, letter, alnum, 'Z', alnum
gstin = re.compile(r"^\d{2}[A-Z]{5}\d{4}[A-Z][A-Z\d]Z[A-Z\d]$")
print(bool(gstin.match("27ABCDE1234F1Z5")))   # True

match, search, findall and named groups

  • re.match checks only at the start of the string.
  • re.search finds the first match anywhere.
  • re.findall returns every match as a list.
  • re.fullmatch requires the whole string to match.

Named groups make results self-documenting:

m = re.search(r"(?P<day>\d{2})/(?P<month>\d{2})/(?P<year>\d{4})", "Delivered on 05/08/2026")
if m:
    print(m["year"], m["month"], m["day"])   # 2026 08 05

Key takeaways

  • Try string methods first; reach for re when the pattern varies.
  • Always use raw strings for patterns and compile patterns you reuse.
  • re.match returns None when nothing matches, so check before using the result.
  • Regex is great for extracting and validating, but do not use it to parse HTML or JSON — use a proper parser.

Practice

Write a function extract_amounts(text) that returns all rupee amounts written like Rs. 1,250 or ₹499.50 as a list of floats. Test it on a short paragraph that contains at least four amounts in different formats.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India