Skip to content
Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
258 lines (178 sloc) 8.27 KB
layout author title date desc img imgdesc imgurl categories tags interesting toc todo
post
Wouter Van Schandevijl
JavaScript RegExp Tutorial
2019-03-04 16:00:00 -0800
A tutorial and cheat-sheet on RegExp testing, matching and replacing in JavaScript.
when-searching-regular-expressions-on-unsplash.jpg
Unsplash picture by Aga Putra
javascript
cheat-sheet
regex
git desc
aloisdg/awesome-regex
A curated collection of awesome Regex libraries, tools, frameworks and software
url desc
RexEgg.com: The world's most tyrannosaurical regex tutorial
url desc
New regular expression features in ECMAScript 6 (7/2015)
git desc
tc39/proposal-string-matchall
Currently in Stage 3: Candidate (3/2019)
url desc
regexr.com: Online, open source tool to learn, build, & test regexes
url desc
regex101.com: Another online regex test tool
title icon
JavaScript RegExp
icon-script
reason url desc
Followup
Check if this got to Stage 4 yet
reason url desc
Too advanced
Replace also works with a function argument for capture side effects

A cheat sheet for the regex syntax in JavaScript.

MDN RegExp Guide {: style="float: right"}

TL&DR

''.test(/^$/);
'ok'.replace(/(.)(.)/g, '$2$1'); // $$, $&, $`, $'

const matchG = 'aaa'.match(/a/g);
matchG == ['a', 'a', 'a'];

const matchNoG = 'str'.match(/(st)r/);
matchNoG == Object.assign(['str', 'st'], {groups: undefined, index: 0, input: 'str'});
matchNoG == /(st)r/.exec('str');

Common Usage

Define yourself a regex:

// Preferred way
const expressionLiteral = /\w+/;

// Only use this for dynamic patterns
const ctor = new RegExp('\\w+');

RegExp.prototype.test

RegExp.prototype.test {: style="float: right"}

Returns true or false.

const didMatch = /a/.test('abc');

String.prototype.replace

String.prototype.replace {: style="float: right"}

Without the g flag, only the first match is replaced. (which makes no difference in the example:)

'dog The'.replace(/(dog) (The)/g, '$2 $1');
Replacement Description
$$ A literal $
$& The matched string
$` Portion before the match
$' Portion after the match
$n With n < 100: the nth captured group (!! 1 indexed !!)
{: .table-code}

String.prototype.match

match() with the g flag:

String.prototype.match {: style="float: right"}

Returns null or all matches as a string[]. There is no captured group info.

const match = 'a_ab_a'.match(/a(b?)/g);
expect(match).toEqual(['a', 'ab', 'a']);

match() without the g flag:
Returns null or the first match and its capturing groups.
The result is an array with additional fields (groups, index and input). exec

(Hence the weird toEqual array syntax in the code below...)

const match = '0abaa'.match(/a(?<theB>b?)/);
expect(match).toEqual([
    0: 'ab', // Entire matched string
    1: 'b',  // First captured group
    groups: {theB: 'b'}, // Results of named groups (ES2018)
    index: 1,
    input: '0abaa'
]);

// Without the g flag, match behaves exactly like exec:
const exec = /a(?<theB>b?)/.exec('0abaa');
expect(exec).toEqual(match);

!! RegExp.prototype.matchAll is "Under Construction" !!

🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 👷 👷 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧

🚧 👷 🚧  proposal-string-matchAll is a Stage 3 Candidate at the moment 🚧 👷 🚧

🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 👷 👷 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧 🚧

RegExp.prototype.exec

RegExp.prototype.exec {: style="float: right"}

When you need the capturing groups of all matches, it's exec to the rescue.

const globbing = /(a)(b2?)/g;
const input = 'ab_ab2';
// Indexes     0  3  

globbing.exec(input);
== Object.assign(['ab', 'a', 'b'], {index: 0});

globbing.exec(input);
== Object.assign(['ab2', 'a', 'b2'], {index: 3});

globbing.exec(input);
== null

Flags

const rl = /ab+c/i;
const rc = new RegExp('ab+c', 'i');

Available flags:

| Flag | Property | Remarks | StackOverflow |------------|--------------------------------------------------------------------------------------------------- | i | .ignoreCase | Case insensitive | g | .global | Do not stop at first match but find all of them | m | .multiline | ^ and $ match beginning/end of each line (otherwise of entire string) | StackOverflow | s | .dotAll | . matches newlines. (ES2018) | u | .unicode | /^.$/u.test('😀') | y | .sticky | Use .lastIndex to match at that specific index only (overwrites the g flag) | StackOverflow | | .flags | Returns a string with the active flags {: .table-code}

Less Common

const flags: string = /a/ig.flags; // "gi"
const src: string = /a/.source; // "a"

String.prototype.search

String.prototype.search {: style="float: right"}

A more powerful version of indexOf. Returns -1 if no match.

const index: number = /a/.search('a');

String.prototype.split

String.prototype.split {: style="float: right"}

Usually used in the form of something like 'a,b,c'.split(','). But also possible to split on regex matches.

"a,b;c".split(/,|;/);
// --> ['a', 'b', 'c']

// Wrap in parentheses to include the separator.
"a,b;c".split(/(,|;)/);
// --> ['a', ',', 'b', ';', 'c']

RegExp.prototype.lastIndex

RegExp.prototype.lastIndex {: style="float: right"}

Used by exec, test, ... with the global (g) flag and for any of the above functions when using the sticky (y) flag.

const input = 'aab';
const regex = /a/g;
regex.test(input); // Returns true. lastIndex is now 1
regex.test(input); // Returns true. lastIndex is now 2
regex.test(input); // Returns false. lastIndex is reset to 0
You can’t perform that action at this time.