Indexing in Regular Expressions in Python

Regular Expressions Mar 19, 2026

Indexing in Regular Expressions in Python

Indexing in regular expressions refers to accessing specific parts of a match using group(), start(), end(), and span(). This is one of the most powerful features of Python’s re module. In data science, it allows you to extract precise substrings, capture groups, and locate matches within large text fields — essential for log parsing, data extraction, feature engineering, and building robust text processing pipelines.

TL;DR — Core Indexing Methods

  • match.group(0) or match.group() → full match
  • match.group(1), match.group(2) → specific capturing groups
  • match.start(), match.end(), match.span() → position of the match
  • Works with both re.search() and re.finditer()

1. Basic Indexing with group()

import re

text = "Order ID: ORD-12345, Amount: $1250.75, Date: 2026-03-19"

match = re.search(r"ORD-(\d+)", text)

print(match.group(0))     # Full match: ORD-12345
print(match.group(1))     # Capturing group 1: 12345

2. Real-World Data Science Examples

# Example 1: Extract multiple fields with groups
pattern = r"Order ID: ORD-(\d+).*Amount: \$([\d.]+)"
match = re.search(pattern, text)

if match:
    order_id = match.group(1)
    amount = match.group(2)
    print(f"Order: {order_id}, Amount: ${amount}")

# Example 2: Find all matches and their positions with finditer
for match in re.finditer(r"\$\d+\.\d{2}", text):
    print(f"Found amount: {match.group(0)} at position {match.span()}")

3. Advanced Indexing with start(), end(), and span()

match = re.search(r"Amount: \$(\d+\.\d{2})", text)

print("Full match start/end:", match.start(), match.end())
print("Group 1 start/end:", match.start(1), match.end(1))
print("Span of full match:", match.span())
print("Span of amount group:", match.span(1))

4. Best Practices in 2026

  • Use numbered groups ((\d+)) for simple extractions
  • Use named groups ((?P<name>\d+)) for more readable code
  • Always check if match is not None before accessing groups
  • Use finditer() when you need positions of all matches
  • Combine with pandas .str.extract() for vectorized extraction on DataFrames

Group Numbers and Names in Practice

Every pair of parentheses in a pattern creates a numbered group, counted by the position of its opening parenthesis from left to right. group(0) is always the whole match. Named groups, written (?P...), get both a name and a number.

Named groups make code easier to maintain because adding a new group does not change how you access existing ones. They also become column names when used with pandas str.extract.

If you need parentheses only for grouping, not capturing, use (?:...), which keeps the numbering simple.

Worked Example: From Log Lines to Columns

Named groups turn log text into a tidy DataFrame.

import pandas as pd

logs = pd.Series(["2026-03-19 ERROR disk full", "2026-03-20 INFO started", "bad line"])
pattern = r"(?P<date>\d{4}-\d{2}-\d{2}) (?P<level>[A-Z]+) (?P<message>.+)"

parts = logs.str.extract(pattern)
print(parts)
print(parts["level"].value_counts(dropna=False))

Each named group becomes a column. The line that does not match produces NaN in every column, which makes invalid rows easy to find and count.

Practical Tips

Write the pattern once with named groups and keep it in a constant near the top of the module. Every function that needs the same fields can then reuse it, and a change to the format only needs one edit.

Test the pattern on a few valid lines and at least one invalid line, and check that the invalid line produces NaN rather than a wrong partial match.

When a pattern grows long, the re.VERBOSE flag lets you spread it over several lines with comments, which makes group names and their purpose easy to review.

Finally, keep the group names short and descriptive, because they become column names in every DataFrame built from the pattern.

Count matches per group with value_counts to spot unexpected values quickly.

Common Mistakes

  • Counting groups from closing parentheses instead of opening ones.
  • Forgetting that group(0) is the whole match.
  • Using capturing groups where (?:...) is enough.
  • Writing patterns without a raw string, which breaks backslashes.

Quick Summary

  • Groups are numbered by opening parenthesis.
  • Named groups are clearer and stable.
  • str.extract turns groups into columns.
  • Non-matching rows become NaN.

Conclusion

Indexing in regular expressions gives you precise control over what you extract and where it appears in the text. In 2026 data science projects, mastering group(), start(), end(), and span() is essential for building robust text parsing pipelines, extracting structured information from logs, and creating high-quality features from unstructured data.

Next steps:

  • Practice extracting multiple fields using capturing groups and indexing on one of your text-heavy datasets

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices