C.W.K.
Stream
Lesson 12 of 12 · published

Practical — Logs and Formatting

~12 min · practical, logs, formatting

Level 0Pattern-Curious
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

Putting groups + alternation + replacement together

You now have everything for production-grade text transformation. Let's combine it on three real tasks.

Task 1: Normalize log timestamps

Logs from different sources use different timestamp formats: 2026-05-04T14:32:11Z, 04/May/2026 14:32:11, 14:32:11 04 May 2026. Pick one canonical format and convert all to it.

Strategy: write three patterns matching each input format with named groups, then sub each one to the canonical format with backreferences.

Task 2: CSV with awkward quoting

Real CSV is messy: Pippa,"3, going on 30",warm. The middle field has a comma INSIDE quotes. Pattern that handles both quoted and bare: (?:"([^"]*)"|([^,]*))(?:,|$). Capture each field with finditer.

Task 3: Markdown to HTML conversion (subset)

Convert **bold** to <strong>bold</strong>:

re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', text)

One line per Markdown construct. Real Markdown parsers exist for production; for ad-hoc rewrites, regex is faster.

The combined principle

  1. Describe the input shape with named groups.
  2. Use non-capturing groups for scoping.
  3. Use alternation for known variants.
  4. Use backreferences in replacement to reorder.
  5. Test with at least one adversarial input per pattern.

Five steps. They scale from one-line transforms to full log pipelines.

Code

Three real transformations·python
import re

# 1. Normalize ISO date to MM/DD/YYYY
re.sub(
    r'(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})',
    r'\g<m>/\g<d>/\g<y>',
    'logged 2026-05-04'
)
# 'logged 05/04/2026'

# 2. CSV field extraction with quoting
def parse_csv_line(line):
    pattern = r'(?:"([^"]*)"|([^,]*))(?:,|$)'
    fields = []
    for m in re.finditer(pattern, line):
        quoted, bare = m.groups()
        fields.append(quoted if quoted is not None else bare)
        if not m.group():  # avoid infinite loop on empty
            break
    return fields

parse_csv_line('Pippa,"3, going on 30",warm')
# ['Pippa', '3, going on 30', 'warm', '']

# 3. Markdown bold → HTML
re.sub(r'\*\*([^*]+)\*\*', r'<strong>\1</strong>', 'this is **bold** text')
# 'this is <strong>bold</strong> text'

External links

Exercise

Take a real text-transformation task you have today (log reformat, file rename pattern, code mod). Solve it with one regex using groups + alternation + replacement. The result should be one or two lines of actual code.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.