
Regular expressions — a powerful tool for string processing
/\$(\$)?([^]*?)\$(\$)?/
Matches the contents of mathematical formulas delimited by single or double $ signs and then renders them.
Delimiter pattern:
/(<[^>]+>|\$\$.+?\$\$|\$.+?\$|&[a-zA-Z]{2,8};)/gim
<[^>]+>: matches an HTML or XML tag.\$\$.+?\$\$: matches syntax similar to LaTeX;+?is a lazy match that consumes as little as possible.\$.+?\$: same idea; double dollar signs render blocks, while single dollar signs render inline formulas.&[a-zA-Z]{2,8};: matches an HTML entity, such as&.|: supports multiple patterns./gim: global matching, multiline mode, and case-insensitive matching.
Fundamentals
How to create one
There are two main ways:
- RegExp:
regexp = new RegExp('pattern','flags') - Literal:
/abc/g
Flags
Common flags:
- g: return all matches.
- i: case-insensitive matching.
- u: enable Unicode character support.
- s: make the dot match newline characters.
- m: enable multiline anchor mode.
Regular-expression methods
Search
string.match(regular expression)
Returns an array of matched characters.
Without /g, the result also has properties such as .index and .input.
Returns null when there is no match.
Replace
string.replace(regular expression, replacement)
// Without the g flag
alert('We will, we will'.replace(/we/i, 'I')); // I will, we will
// With the g flag
alert('We will, we will'.replace(/we/gi, 'I')); // I will, I will
The replacement parameter
| Symbol | Behavior in the replacement string |
|---|---|
$& | Insert the entire match. |
| `$“ | Insert the part of the string before the match. |
$' | Insert the part of the string after the match. |
$n | If n is a one- or two-digit number, insert the contents of the nth group; see capturing groups. |
$<name> | Insert the contents of the parentheses with the given name; see capturing groups. |
$$ | Insert the $ character. |
Test
string.test(regular expression)
Returns true if there is at least one match; otherwise returns false.
Character classes and special characters
Basic character classes
\d digit, 0–9
\s space, such as \n and \t
\w word: letters, numbers, and underscore _
Inverse character classes
\D any non-digit character.
\S any non-space character.
\W any non-word character.
The dot (.) matches “any character.”
The dot . is a special character class that matches “any character except a newline.”
For example:
alert('Z'.match(/./)); // Z
With the s flag, the dot character class matches any character
alert('A\nB'.match(/A.B/s)); // A\nB (matched!)
Anchors and boundaries
Start and end anchors
The caret ^ and dollar sign $ have special meanings in regular expressions. They are called “anchors.”
The caret ^ matches the beginning of the text, while $ matches the end.
Together, they can achieve an exact match.
Multiline mode
Adding the multiline flag lets the expression match the beginning and end of each line.
Word boundary
\b
There are three positions that can serve as word boundaries:
- At the beginning of a string when the first character is a word character,
\w. - Between two characters when one is a word character,
\w, and the other is not. - At the end of a string when the last character is a word character,
\w.
Sets and ranges
Sets
Several characters or character classes inside square brackets […] mean “any one of the given characters.”
[QWER] matches any of these four characters: 'Q', 'W', 'E', or 'R'.
Ranges
Square brackets can also contain a character range.
For example, [a-z] matches a character from a to z, and [0-5] matches a digit from 0 to 5.
[0-9A-F] contains two ranges. It matches a character that is either a digit from 0 to 9 or a letter from A to F.
Excluding a range
In addition to ordinary ranges, there is an “exclude” range such as [^…].
Putting ^ at the beginning means “any character except the given characters.”
[^aeyo]matches any character except'a','e','y', or'o'.[^0-9]matches any non-digit character and is equivalent to\D.[^\s]matches any non-space character and is equivalent to\S.
Escaping rules
When we want to match a special character literally, we usually escape it, as in \.. To match a backslash, use \\, and so on.
Inside square brackets, most special characters can be used without escaping:
. + ( )do not need escaping.- A hyphen
-at the beginning or end (where it does not define a range) does not need escaping. - A caret
^only needs special handling at the beginning, where it means exclusion. - A closing bracket
]is always escaped when we need to search for that symbol.
Ranges and the u flag
If a set contains surrogate pairs, the u flag is required for them to work correctly.
For example, let us search for [𝒳𝒴] in the string 𝒳.
Quantifiers
Basic quantifiers
An exact number
{5}` => `\d{5}` === `\d\d\d\d\d
A range
{3,5} matches 3–5 characters
{,5} matches at most 5 characters
{6,} matches at least 6 characters
Quantifier shorthand
+: one or more, equivalent to{1,}*: zero or more, equivalent to{0,}?: zero or one, equivalent to{0,1}
Greedy and lazy quantifiers
Let us look at an example first:
let regexp = /".+"/g;
let str = 'a "witch" and her "broom" is one';
alert(str.match(regexp)); // "witch" and her "broom"
…the result is clearly different from what we expected!
In greedy mode (the default), quantifiers repeat as many times as possible.
Lazy quantifiers
By default, quantifiers are greedy, meaning that they match as many characters as possible. Add ? after a quantifier to make it lazy, meaning it matches as few characters as possible.
*?: zero or more, as few as possible.+?: one or more, as few as possible.??: zero or one, as few as possible.{n,m}?: n to m, as few as possible.{n,}?: at least n, as few as possible.
Comparison
Suppose we have the string "aaaaa".
-
Greedy matching
Pattern:
a+Result:
["aaaaa"] -
Lazy matching
Pattern:
a+?Result:
["a", "a", "a", "a", "a"]
Capturing groups
(...) is called a “capturing group.”
- It lets you return part of a match as a separate item in the result array.
- If a quantifier follows the parentheses, it treats the parentheses as one unit.
Named groups
Put ?<name> immediately after the opening parenthesis to name the group.
For example, let us find a date in year-month-day format:
let dateRegexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
let str = '2024-06-18';
let groups = str.match(dateRegexp).groups;
alert(groups.year); // 2024
alert(groups.month); // 06
alert(groups.day); // 18
Capturing groups in replacement
let str = 'John Bull';
let regexp = /(\w+) (\w+)/;
alert(str.replace(regexp, '$2, $1')); // Bull, John
For named parentheses, use $<name> as the reference.
Non-capturing groups
This is somewhat abstract; try it a few more times.
Sometimes we need parentheses to apply a quantifier correctly, but we do not want their contents to appear in the result.
NOTE
Like building with blocks, the more pieces you have, the more complex it becomes.
Backreferences
Suppose we want to match both '...' and "...".
If the pattern is ['"](.*?)['"], we run into this problem:
let str = `He said: "She's the one!".`;
let regexp = /['"](.*?)['"]/g;
// Not the result we want
alert(str.match(regexp)); // "She'
Debugging
{n} caused the MDX file to crash because it was parsed as a variable.

