Overview
Use a real parser when one exists (URLs, dates, HTML, JSON); use regex for small, flat text. Flavors differ: PCRE and Python are Perl-like, JavaScript has its own rules, and POSIX tools (grep -E, sed -E) lack \d and lookarounds. Python specifics are on python-regex; patterns below were tested in Python 3.11 and Node 22.
Syntax
Check which engine you target; spelling and support differ.
| Syntax | Meaning |
|---|---|
. | Any character except newline (any with the s flag). |
\d \w \s and \D \W \S | Digit, word, whitespace; negated forms. |
[abc] [^abc] [a-z] | Set, negated set, range. |
^ $ | Start and end of input; of each line with m. |
\b \B | Word boundary, non-boundary. |
\A \Z | Absolute start and end in Python. PCRE uses \A \z (its \Z also matches before a final newline). Not in JavaScript. |
? * + {n} {n,} {n,m} | Quantifiers; add ? for lazy: *?, +?, {n,m}?. |
*+ ++ (?>...) | Possessive and atomic (PCRE, Java, Python 3.11+; not JavaScript). |
(...) (?:...) | Capturing and non-capturing group. |
(?<n>...) / (?P<n>...) | Named group: JavaScript and PCRE / Python. |
\1 \k<n> (?P=n) | Backreferences: numbered / JavaScript named / Python named. |
(?=...) (?!...) (?<=...) (?<!...) | Lookahead and lookbehind, positive and negative; \d+(?= dollars) matches the digits only, (?<=\$)\d+ the digits after $. |
a|b | Alternation. |
Flags by engine
Set flags explicitly per engine rather than assuming parity.
| Effect | Python | JavaScript | PCRE inline |
|---|---|---|---|
| Case-insensitive | re.I | i | (?i) |
^ $ per line | re.M | m | (?m) |
. matches newline | re.S | s | (?s) |
| Ignore pattern whitespace and comments | re.X | not available | (?x) |
| Find all matches | findall, finditer | g | engine API |
| Unicode matching | default for str | u (or v) | engine option, such as (*UTF) |
\p{...} property classes | not in re; use the regex module | needs u or v | supported |
| Sticky match at an index | pattern.match(s, pos) | y | \G |
| Match indices | not available | d | not available |
| ASCII-only classes | re.A | default | engine option |
Patterns
Anchor validation patterns; in Python use re.fullmatch.
| Target | Pattern |
|---|---|
| IPv4 | ^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$ |
| Port 1-65535 | ^([1-9]\d{0,3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$ |
| ISO date | ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ (checks ranges, not Feb 30) |
| RFC 3339 datetime | ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$ |
| UUID, versions 1 to 8 | ^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ (use 4 for v4 only) |
| Hex color | ^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$ |
| Slug | ^[a-z0-9]+(?:-[a-z0-9]+)*$ |
# Email (pragmatic; confirm real addresses by sending mail)
^[\w.!#$%&'*+/=?^`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$
# URL (http and https; catches obvious garbage only)
^https?://[^\s/$.?#].[^\s]*$
Use a parser for the rest: URL in JavaScript, urllib.parse and ipaddress in Python. A naive (\d{1,3}\.){3}\d{1,3} accepts 999.999.999.999, and a short IPv6 regex rejects ::.
Gotchas
Avoid these; each matches too much, too little, or hangs.
| Gotcha | Fix |
|---|---|
Python $ also matches before a trailing newline. | Use fullmatch or \Z. |
\d matches any Unicode digit in Python str patterns but only 0-9 in JavaScript, and POSIX -E has no \d. | Write [0-9] when you mean ASCII digits everywhere. |
A JavaScript /g regex keeps lastIndex, so .test() alternates results across calls. | Drop g for tests, or reset lastIndex. |
| Python lookbehind must be fixed-width; JavaScript allows variable width. | Restructure, or use the third-party regex module. |
| POSIX tools have no lookaround. | Use grep -P (GNU only) or perl -ne. |
Nested quantifiers like (a+)+ backtrack catastrophically. | Simplify the pattern and cap input length. |
| An unanchored validation pattern matches inside longer text. | Anchor with ^ and $. |