Regular Expressions Cheatsheet
Flags and Modifiers
Use this Regular Expressions reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
The common flags
| Flag | Name | Effect |
|---|---|---|
i | ignore case | a matches A |
m | multiline | ^ and $ match at every line break |
s | dotall / single line | . also matches newline |
x | extended / verbose | unescaped whitespace and # comments ignored |
u | unicode | JS: \p{...}, \u{...}, code-point semantics |
v | unicode sets | JS: u plus set operations inside classes |
g | global | JS only, keep scanning past the first match |
y | sticky | JS only, match must start exactly at lastIndex |
d | indices | JS only, populate match.indices |
A | ASCII | Python: make \d \w \s \b ASCII-only |
U | ungreedy | PCRE and Go: swap greedy and lazy meanings |
J | dup names | PCRE: allow two groups with the same name |
m and s are independent. m does not let . cross a newline, and s does not move ^.
Setting flags per language
// literal, flags after the closing slash /^\d+$/gim.test(s) new RegExp("^\\d+$", "gim") "aAbA".replace(/a/gi, "-") // "--b-", i widens g
import re re.search(r'^\d+$', s, re.I | re.M) # bitwise OR re.compile(r'^\d+$', re.IGNORECASE) # long names exist for all of them # no global flag, the function picks the behavior instead re.search(...) # first match re.findall(...) # every match re.finditer(...) # every match, lazily, with positions re.sub(...) # replace all by default, cap it with count=1
grep -i -E 'pattern' file # case-insensitive ERE sed -E 's/x/y/gI' file # g = every match on the line, I = ignore case
regexp.MustCompile(`(?is)^a.b$`) // Go has no flag argument, only inline
Inline flag syntax
| Form | Scope |
|---|---|
(?i) | on for the rest of the pattern |
(?i:...) | on inside the group only |
(?-i:...) | off inside the group only, even under an outer i |
(?im-sx:...) | several at once, - separates the off list |
re.search(r'(?i:hello) World', 'HELLO World') # matches re.search(r'(?i)hello world', 'HELLO WORLD') # matches
- Python allows a bare
(?i)only at the very start of the pattern. Anywhere else it raisesglobal flags not at the start of the expression. Use(?i:...)when it needs to be local. - JavaScript supports no inline flags at all.
/(?i)ab/is a syntax error, and/\p{L}/withoutuquietly matches the literal textp{L}instead of erroring. - Go supports
(?i),(?m),(?s),(?U)and the scoped forms, but not(?x).
Extended mode x
Whitespace and # comments become invisible, which makes a long pattern readable. Escape the spaces you actually want, or put them in a class.
phone = re.compile(r''' (?P<area> \d{3} ) # area code [-.\s]? # optional separator (?P<exch> \d{3} ) [-.\s]? (?P<line> \d{4} ) ''', re.X) phone.search('call 555-867-5309').groupdict() # {'area': '555', 'exch': '867', 'line': '5309'}
Inside x mode, a b matches ab. To match a real space write a\ b, a[ ]b, or a\sb. Whitespace inside a bracket expression is still literal, so [a b] includes the space.
Case-insensitive is not case-folding
i compares character by character, so it cannot handle a one-to-many fold.
bool(re.search('straße', 'STRASSE', re.I)) # False, ß vs SS bool(re.search('É', 'é', re.I)) # True, simple 1:1 fold
/σ/iu.test("Σ") // true, sigma folds /k/iu.test("K") // true, U+212A KELVIN SIGN folds to k
For real language-aware comparison, normalize first (str.casefold() in Python, s.toLowerCase() plus normalize("NFKC") in JavaScript) and match on the normalized form. Turkish dotless i and Greek final sigma will still bite.
Flags that change results, not just matching
iwidens what a class matches, so[a-z]withialso matchesA-Z, and[^a-z]withitherefore matches neither case.smakes.*swallow the whole document. When parsing line-oriented data, keepsoff and use[\s\S]where you genuinely mean any character.Uin PCRE and Go inverts greediness, so.+becomes lazy and.+?becomes greedy. It reads as a bug to everyone else, prefer explicit?.- JavaScript's
gmakes a regex object stateful throughlastIndex. Reusing onegregex across calls to.test()skips matches. Create it fresh, or usematchAllandreplaceAll.
const r = /a/g; r.test("aa"); // true, lastIndex 1 r.test("aa"); // true, lastIndex 2 r.test("aa"); // false, lastIndex reset to 0