flashman
← All guides

Unicode-safe regex and normalization guide

Build Unicode-aware text matching by separating code units, code points, grapheme clusters, normalization, locale rules, security boundaries, and runtime regex support.

2026-08-30 · 8 min read

  • regex
  • unicode
  • text-processing

Text displayed as one character may contain one code point, several combining code points, or a multi-code-point emoji sequence. The same accented word can also have canonically equivalent composed and decomposed representations.

Regex behavior depends on the language runtime, Unicode version, flags, and pattern features. Treating text as ASCII or assuming one visible symbol equals one code unit creates validation failures and unsafe truncation.

Choose the unit your feature needs

Protocol syntax may be defined in ASCII bytes, identifier rules may operate on Unicode code points, and user-facing cursor movement or length limits usually need grapheme clusters. Write this decision into the requirement before choosing a regex.

  • Use explicit ASCII classes for specifications that require ASCII.
  • Use Unicode property escapes for broad script-aware categories when supported.
  • Use a grapheme-aware library for displayed-character boundaries.
  • Do not use byte length, code units, and visible length interchangeably.

Normalize at a controlled boundary

Normalization forms such as NFC can make canonically equivalent sequences consistent for search or identifiers. Apply one documented form before comparison and indexing when the product requires equivalence, and preserve the original display value if users expect it.

Do not normalize signed bytes, hashes, encrypted values, file formats, or protocol fields unless their specification says to do so. A visually harmless transformation changes the byte sequence and invalidates integrity checks.

Account for security and locale

Normalization does not solve visually confusable characters, mixed-script identifiers, bidirectional controls, or locale-specific case mapping. High-risk identifiers may need a restricted profile and confusable-character review beyond regex validation.

  • Define whether mixed scripts are permitted in identifiers.
  • Handle case folding separately from normalization.
  • Make invisible control policy explicit.
  • Bound input length before running complex patterns.

Test the exact runtime

Use Flashman's regex tester for representative strings, diff tool to reveal sequence differences, HTML entities tool for escaped web input, URL tool for percent-encoded text, and case converter to explore non-authoritative casing behavior. Confirm final semantics in the exact production engine.

Maintain fixtures for composed and decomposed accents, combining marks, emoji sequences, non-Latin scripts, mixed directionality, line separators, malformed transport input, and runtime upgrades that change the bundled Unicode data.

Try these tools