X Xerobit

Regex Replace in JavaScript — String.replace() and replaceAll() with Patterns

Master JavaScript regex replace: String.replace() with capture groups, replaceAll() vs global flag, using functions as replace values, and common patterns for sanitizing...

Mian Ali Khalid · · 4 min read
Use the tool
Regex Tester
Test regular expressions with live match highlighting and explanation.
Open Regex Tester →

String.replace() replaces the first match; String.replaceAll() replaces all. Both accept regex patterns. Capture groups let you reorder or transform matched content.

Test your patterns with the Regex Tester.

Basic replace with regex

// Replace first match (no /g flag):
'hello world hello'.replace(/hello/, 'hi');
// "hi world hello"

// Replace all matches (with /g flag):
'hello world hello'.replace(/hello/g, 'hi');
// "hi world hi"

// String.replaceAll() — equivalent to /g flag for literal strings:
'hello world hello'.replaceAll('hello', 'hi');
// "hi world hi"

// replaceAll() with regex requires the /g flag:
'hello world hello'.replaceAll(/hello/g, 'hi');  // ✓
'hello world hello'.replaceAll(/hello/, 'hi');   // TypeError: missing /g

Capture groups in replacement string

Special $ sequences reference capture groups:

// $1, $2 reference capture groups by number:
'John Smith'.replace(/(\w+)\s(\w+)/, '$2, $1');
// "Smith, John"

// Named capture groups with $<name>:
'2024-05-12'.replace(
  /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
  '$<month>/$<day>/$<year>'
);
// "05/12/2024"

// $& = the entire match:
'hello world'.replace(/\w+/g, '[$&]');
// "[hello] [world]"

// $` = text before match, $' = text after match (rarely used):
'aXb'.replace(/X/, '($`-$\')');
// "(a-b)"

Function as replacement

When the second argument is a function, it’s called with each match:

// Arguments: (match, ...captureGroups, offset, originalString)

// Uppercase each word:
'hello world foo'.replace(/\b\w+/g, word => word.toUpperCase());
// "HELLO WORLD FOO"

// Increment numbers:
'item1 item2 item3'.replace(/\d+/g, n => parseInt(n) + 10);
// "item11 item12 item13"

// With capture groups:
'2024-05-12'.replace(
  /(\d{4})-(\d{2})-(\d{2})/,
  (match, year, month, day) => `${month}/${day}/${year}`
);
// "05/12/2024"

Common patterns

Slugify URL:

function slugify(text) {
  return text
    .toLowerCase()
    .replace(/[^\w\s-]/g, '')     // Remove non-word chars (except spaces and hyphens)
    .replace(/[\s_]+/g, '-')       // Replace spaces/underscores with hyphens
    .replace(/^-+|-+$/g, '');      // Trim leading/trailing hyphens
}

slugify('Hello, World! This is a Test.');  // "hello-world-this-is-a-test"
slugify('  multiple   spaces  ');          // "multiple-spaces"

Strip HTML tags:

function stripHtml(html) {
  return html.replace(/<[^>]*>/g, '');
}

stripHtml('<p>Hello <strong>world</strong></p>');  // "Hello world"

Format phone numbers:

function formatPhone(digits) {
  return digits.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
}

formatPhone('5551234567');  // "(555) 123-4567"

Camel case to kebab case:

function camelToKebab(str) {
  return str.replace(/([A-Z])/g, (match, char) => `-${char.toLowerCase()}`);
}

camelToKebab('backgroundColor');  // "background-color"
camelToKebab('userAgentString');   // "user-agent-string"

Template variable replacement:

function renderTemplate(template, vars) {
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => vars[key] ?? match);
}

renderTemplate('Hello {{name}}, you are {{age}} years old.', {
  name: 'Alice',
  age: 30,
});
// "Hello Alice, you are 30 years old."

Lookahead in replacements

// Add thousands separator to numbers:
function addCommas(n) {
  return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

addCommas(1234567);  // "1,234,567"

// Insert line breaks before capital letters (camel case splitter):
'camelCaseString'.replace(/(?=[A-Z])/g, ' ');
// "camel Case String"

replaceAll with a function (ES2021)

// replaceAll also accepts a function (with /g required):
const text = 'foo bar baz foo';
text.replaceAll(/foo/g, (match, offset) => {
  return `[${match}@${offset}]`;
});
// "[foo@0] bar baz [foo@12]"

Performance: precompile regex for hot paths

// ❌ Regex compiled on every call (slow in loops):
function sanitize(str) {
  return str.replace(/[<>&"']/g, '&amp;');  // Compiled each call
}

// ✅ Compile once, reuse:
const UNSAFE_CHARS = /[<>&"']/g;
const HTML_ENTITIES = { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' };

function sanitize(str) {
  return str.replace(UNSAFE_CHARS, ch => HTML_ENTITIES[ch]);
}

Related posts

Related tool

Regex Tester

Test regular expressions with live match highlighting and explanation.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.