Repository navigation
Unicode support
RE2 always works in Unicode mode. In most cases this is either invisible or preferred.
const RE2 = require('re2');
new RE2('\\p{Script=Cyrillic}+').exec('abc привет')[0]; // 'привет'
new RE2('[^\\p{ASCII}]').test('é'); // trueFor applications that need tight control, the static property RE2.unicodeWarningLevel governs what happens when a non-Unicode regular expression is created.
If a regular expression lacks the u flag, it is added silently by default:
const RE2 = require('re2');
const x = /./;
x.flags; // ''
const y = new RE2(x);
y.flags; // 'u'Values of RE2.unicodeWarningLevel:
-
'nothing'(default) — silently addu. -
'warnOnce'— warn once, then silently addu. Assigning this value resets the one-time flag. -
'warn'— warn every time, still addu. -
'throw'— throwSyntaxError. - Any other value is silently ignored, leaving the previous value unchanged.
Warnings and exceptions help audit an application for stray non-Unicode regular expressions.
RE2.unicodeWarningLevel is global and shared across threads, so take care in multi-threaded environments.
node-re2 follows MDN's Unicode character class escape reference — the same set of property escapes that JavaScript's native RegExp accepts with the u flag.
Supported categories:
-
General_Category — both short names (for example,
\p{L},\p{Lu}) and long names (for example,\p{Letter},\p{Uppercase_Letter}). Thegc=andGeneral_Category=prefixes also work:\p{gc=Letter},\p{General_Category=Letter}. -
Script — for example,
\p{Script=Latin},\p{sc=Cyrillic}. ISO 15924 four-letter codes are accepted as well:\p{sc=Latn}. -
Script_Extensions — for example,
\p{Script_Extensions=Hani},\p{scx=Latn}. Matches characters whose Script_Extensions list includes the named script (a superset ofScript=). -
Binary properties — the full ECMAScript set of binary properties, including:
-
Alphabetic,ASCII,ASCII_Hex_Digit,Hex_Digit,White_Space,Math,Dash,Diacritic,Quotation_Mark,Bidi_Mirrored,Bidi_Control,Default_Ignorable_Code_Point -
Lowercase,Uppercase,Cased,Case_Ignorable,Changes_When_Lowercased,Changes_When_Uppercased,Changes_When_Casefolded,Changes_When_Casemapped,Changes_When_Titlecased,Changes_When_NFKC_Casefolded -
ID_Start,ID_Continue,XID_Start,XID_Continue,Pattern_Syntax,Pattern_White_Space -
Emoji,Emoji_Presentation,Emoji_Modifier,Emoji_Modifier_Base,Emoji_Component,Extended_Pictographic,Regional_Indicator -
Grapheme_Base,Grapheme_Extend,Extender,Variation_Selector,Join_Control,Logical_Order_Exception,Sentence_Terminal,Terminal_Punctuation,Soft_Dotted,Radical,Unified_Ideograph,Ideographic,IDS_Binary_Operator,IDS_Trinary_Operator,Noncharacter_Code_Point,Deprecated,Any,Assigned
Short aliases listed in PropertyAliases.txt are accepted alongside the canonical names:
\p{Alpha}≡\p{Alphabetic},\p{Hex}≡\p{Hex_Digit},\p{Lower}≡\p{Lowercase}, and so on. -
The negated form \P{...} and use inside character classes ([\p{L}\p{Emoji}], [^\p{ASCII}]) work for every category.
Not supported: Properties of Strings (\p{Basic_Emoji}, \p{RGI_Emoji}, and so on). These match multi-codepoint sequences and require the v flag, which RE2 does not model.
Tables are baked in at build time from Unicode 17.0. To target a newer Unicode version, bump @unicode/unicode-XX.X.X in devDependencies and run node scripts/gen-unicode-properties.mjs.
A \p{...} or \P{...} escape stands for a character class that can hold hundreds of codepoint ranges. Building that class takes memory and time, and the cost repeats for every occurrence of the escape in a pattern.
node-re2 adds to the cost for some properties. RE2 supports General_Category and Script natively, and node-re2 passes those escapes to it unchanged. For binary properties, such as Alphabetic and Emoji, and for Script_Extensions, node-re2 writes the full list of ranges into the pattern, once for each occurrence. For example, \p{Assigned} becomes about 12 KB of pattern text, and \p{Grapheme_Base} about 14 KB.
The escapes that RE2 handles natively are costly too, because RE2's parser builds a separate class for every occurrence. RE2's memory budget (max_mem, 8 MiB by default, set by the maxMem option of RE2.Set) applies when RE2 compiles the parsed pattern, so nothing limits the parse itself. The built-in RegExp also builds a class for every occurrence.
The following table shows the approximate memory that each occurrence takes while a long pattern is parsed:
| Escape | Expanded by node-re2 | RE2 |
RegExp |
|---|---|---|---|
\p{Script=Greek} |
No | 3 KiB | 1 KiB |
\p{L} or \pL
|
No | 32 KiB | 13 KiB |
\p{Assigned} |
Yes | 60 KiB | 13 KiB |
\p{Grapheme_Base} |
Yes | 75 KiB | 27 KiB |
The numbers come from Node.js 26.13.0 on Linux x64, with patterns that repeat one escape thousands of times. RegExp rejects \pL, because JavaScript requires the braces.
A pattern that compiles costs more, because compiling adds its own memory: a pattern of 400 \pL escapes takes about 65 MiB to build. With the default budget, a pattern holds a few hundred large classes before RE2 rejects it with SyntaxError: pattern too large - compile failed, and the parse spends its memory before that error. A pattern of a few hundred kilobytes can take several gigabytes and run the process out of memory. For example, each of the following lines stops a process limited to 2 GiB of address space:
new RE2('\\pL'.repeat(100000), 'u'); // a 300 KB pattern
new RegExp('\\p{L}'.repeat(400000), 'u'); // a 2 MB patternTo keep the cost down:
- Use the narrowest class that fits your data. The cost grows with the number of ranges in the class.
- Repeat a class with
+or*. A counted repeat costs as much as writing the class out:\pL{400}takes as much memory to build as 400 copies of\pL. - Build a pattern once and reuse the
RE2object. - If you build patterns from untrusted input, limit their length and the number of their
\pand\Pescapes before you pass them toRE2orRegExp. Neither engine limits the memory that a pattern takes to parse.
Installing
Using
Troubleshooting
- Problem: ABI mismatch in Electron
- Problem: build vs prod environments
- Problem: non-ASCII install path
Developers
Research and notes
- Notes on building alternatives
- Related projects
- FilteredRE2 evaluation
- RE2 lookbehinds fork assessment
- V8 Fast API assessment
- V8 non-backtracking RegExp engine
Project
Repository · README · prebuilds via install-artifact-from-github