Regex Groups and String Methods

This section covers how to capture parts of matches and how to use regex with string methods.

Groups and Capturing

Capturing Groups

Parentheses create capturing groups:

const regex = /(\d{3})-(\d{4})/;
const match = "555-1234".match(regex);

console.log(match[0]); // "555-1234" (full match)
console.log(match[1]); // "555" (first group)
console.log(match[2]); // "1234" (second group)

Named Groups

const regex = /(?<area>\d{3})-(?<number>\d{4})/;
const match = "555-1234".match(regex);

console.log(match.groups.area); // "555"
console.log(match.groups.number); // "1234"

Non-Capturing Groups

Use (?:...) when you need grouping but do not need to capture:

// Captures "http" or "https"
const regex1 = /(https?):\/\//;

// Groups but doesn't capture
const regex2 = /(?:https?):\/\//;

Backreferences

Reference captured groups within the pattern:

// Match repeated words
const regex = /\b(\w+)\s+\1\b/;
console.log(regex.test("the the")); // true
console.log(regex.test("the cat")); // false

Alternation

Use | for “or”:

/cat|dog/.test("I have a cat"); // true
/cat|dog/.test("I have a dog"); // true

// Group alternatives
/(red|green|blue) car/.test("red car"); // true

Lookahead and Lookbehind

These are assertions. They check what comes before or after a position, and they do not consume any characters:

Pattern Name Meaning
(?=...) Positive lookahead Followed by
(?!...) Negative lookahead Not followed by
(?<=...) Positive lookbehind Preceded by
(?<!...) Negative lookbehind Not preceded by
// Password must have a digit
/(?=.*\d).{8,}/.test("password1"); // true
/(?=.*\d).{8,}/.test("password"); // false

// Match "foo" not followed by "bar"
/foo(?!bar)/.test("foobar"); // false
/foo(?!bar)/.test("foobaz"); // true

// Match number preceded by $
/(?<=\$)\d+/.exec("$100"); // ["100"]

RegExp and String Methods

Testing for Matches with RegExp.prototype.test()

Returns a boolean:

/\d+/.test("abc123"); // true

Finding Matches with match()

Returns different output depending on the g flag:

"hello world".match(/\w+/); // ["hello", index: 0, ...]
"hello world".match(/\w+/g); // ["hello", "world"]

Iterating All Matches with matchAll()

Returns an iterator of all matches with groups. If you pass a regex, it must have the g flag:

const regex = /(\w+)@(\w+)/g;
const text = "foo@bar baz@qux";

for (const match of text.matchAll(regex)) {
  console.log(match[0], match[1], match[2]);
}
// "foo@bar" "foo" "bar"
// "baz@qux" "baz" "qux"

Returns the index of the first match:

"hello world".search(/wo/); // 6
"hello world".search(/xyz/); // -1

Replacing Matches with replace()

Replace matched text:

"hello world".replace(/world/, "JavaScript");
// "hello JavaScript"

// With capturing groups
"John Smith".replace(/(\w+) (\w+)/, "$2, $1");
// "Smith, John"

// With function
"hello".replace(/./g, (char) => char.toUpperCase());
// "HELLO"

Replacing All Occurrences with replaceAll()

If the pattern is a regex, it must include the g flag:

"a-b-c".replaceAll("-", "_"); // "a_b_c"
"a-b-c".replaceAll(/-/g, "_"); // "a_b_c"

Splitting Strings with split()

Split a string by a pattern:

"a, b,  c".split(/,\s*/); // ["a", "b", "c"]