All writing2026.09.22 · CS 513 · Theory and Practice of Data Cleaning · 2 min

Regular Expressions for Data Cleaning: Match Structure, Not Meaning

Build testable regexes for validation, extraction, and transformation while keeping parsing and semantic checks separate.

Regular expressions describe patterns in text. In data cleaning they are useful for three distinct jobs: validating a shape, extracting components, and transforming a known representation. Problems begin when a shape match is treated as proof of meaning.

Read a pattern in layers

For an IPv4-like shape:

^(\d{1,3}\.){3}\d{1,3}$
  • ^ and $ anchor the whole value;
  • \d{1,3} matches one to three digits;
  • \. matches a literal dot;
  • {3} repeats the grouped prefix three times.

It accepts 999.999.999.999, so it validates syntax but not the numeric domain. Parse the four components and enforce 0..255 separately.

In plain terms: regex can recognize the shape of an address on an envelope. It cannot prove the address exists.

Match, extract, and replace are different operations

import re

raw = "2026/9/7"
m = re.fullmatch(r"(\d{4})/(\d{1,2})/(\d{1,2})", raw)
if m:
    year, month, day = map(int, m.groups())

After extraction, use a date library to validate month lengths and leap years. Only then emit an ISO value such as 2026-09-07.

A replacement should target what was captured:

re.sub(r"^([^,]+),\s*([^,]+)$", r"\2 \1", "Lin, Johnny")

This transformation is safe only if the source convention is known. Names are not universally two comma-separated tokens.

Avoid the common traps

Trap Symptom Better approach
Missing anchors Valid substring inside invalid text passes Use full match for validation
Greedy wildcard One group consumes too much Use explicit delimiters or non-greedy match
Catastrophic backtracking Runtime spikes on crafted input Simplify nested repetition and bound length
One giant pattern Impossible to review or explain Parse in stages with named groups
Engine assumptions Pattern works in one tool only Record flavor and flags

Unicode also matters. \w, case folding, and character classes behave differently across engines and flags. Test accents, non-Latin scripts, and composed versus decomposed characters when the dataset contains them.

Build a test matrix before mass editing

Case Input Expected
Normal john@example.com accept
Boundary one-character local part accept if policy allows
Malformed missing domain reject
Near miss trailing comment or space normalize or reject explicitly
Adversarial very long repeated text finish quickly

Store the examples beside the cleaning rule. A regex without positive and negative fixtures is an undocumented guess.

Know when to stop using regex

Use a parser for nested formats, CSV quoting, JSON, URLs, dates, and programming-language syntax. Use reference data or business rules for identity and geography. Regex remains valuable at the boundary: extracting a candidate or rejecting an impossible shape before stronger validation.

Review card

  • Anchor validation patterns to the whole value.
  • Separate syntactic matching from domain and semantic validation.
  • Extract components first; canonicalize only after validation.
  • Record regex flavor, flags, and Unicode assumptions.
  • Test valid, invalid, boundary, near-miss, and adversarial inputs.
  • Prefer a real parser when the format has nested grammar.

Regular expression 描述 text pattern。在 data cleaning 裡主要做三件事:驗證 shape、抽取 component、轉換已知 representation。問題通常發生在把「形狀 match」誤當成「語意正確」。

分層讀 pattern

IPv4-like shape:

^(\d{1,3}\.){3}\d{1,3}$
  • ^$ anchor 整個 value;
  • \d{1,3} 匹配 1–3 個 digit;
  • \. 匹配 literal dot;
  • {3} 重複 grouped prefix 三次。

它也接受 999.999.999.999,所以只驗證 syntax,沒有驗 numeric domain。四段 parse 完後,仍要分別檢查 0..255

白話來說: Regex 能認出信封上地址的形狀,不能證明那個地址真的存在。

Match、extract、replace 是不同 operation

import re

raw = "2026/9/7"
m = re.fullmatch(r"(\d{4})/(\d{1,2})/(\d{1,2})", raw)
if m:
    year, month, day = map(int, m.groups())

Extraction 之後要用 date library 驗證月份天數和 leap year,確認後才能輸出 2026-09-07

Replacement 也要只處理 captured component:

re.sub(r"^([^,]+),\s*([^,]+)$", r"\2 \1", "Lin, Johnny")

只有 source convention 明確時這才安全;人名並不普遍等於兩個 comma-separated token。

常見陷阱

陷阱 症狀 改法
沒有 anchor Invalid text 裡一小段 valid 就通過 Validation 使用 full match
Greedy wildcard Group 吃掉太多內容 明確 delimiter 或 non-greedy
Catastrophic backtracking 特定 input 令 runtime 暴增 簡化 nested repetition、限制長度
一個超大 pattern 無法 review 與解釋 分階段 parse、使用 named group
假設 engine 相同 換工具後行為不同 記錄 flavor 與 flag

Unicode 也會影響 \w、case folding 與 character class。Dataset 有 accent、非拉丁文字或 composed/decomposed form 時,都要加 fixture。

Mass edit 前先建 test matrix

Case Input Expected
Normal john@example.com accept
Boundary 一字元 local part policy 允許則 accept
Malformed 缺 domain reject
Near miss 尾端空白或 comment 明確 normalize 或 reject
Adversarial 很長的重複 text 必須快速結束

把例子和 cleaning rule 放在一起。沒有 positive/negative fixture 的 regex,只是沒文件的猜測。

何時不要再用 regex

Nested format、CSV quoting、JSON、URL、date 與 programming-language syntax 應交給 parser;identity、geography 要用 reference data 或 business rule。Regex 適合留在 boundary:先抽 candidate,或在進入強驗證前排除不可能的 shape。

複習卡

  • Validation pattern 要 anchor 全值。
  • Syntax match 與 domain/semantic validation 分開。
  • 先 extract component,驗證後才 canonicalize。
  • 記錄 regex flavor、flag 與 Unicode assumption。
  • 測 valid、invalid、boundary、near-miss、adversarial input。
  • Format 有 nested grammar 時,優先用真正 parser。