Test Regex Replace: Substitution Patterns Across Languages

Replacement is where regex flavours diverge most visibly. The matching side is largely portable; the replacement string syntax is not, and copying one between languages inserts literal text where a capture should go.

Two replacement syntaxes

JavaScript, PHP, C# and Java use $1. Python and sed use \1. Named groups differ too:

// JavaScript
'2026-08-29'.replace(/(\d{4})-(\d{2})/, '$2/$1');     // '08/2026-29'
'2026-08'.replace(/(?<y>\d{4})/, '$<y>');

# Python
re.sub(r'(\d{4})-(\d{2})', r'\2/\1', '2026-08-29')
re.sub(r'(?P<y>\d{4})', r'\g<y>', '2026-08')

# sed
sed -E 's/([0-9]{4})-([0-9]{2})/\2\/\1/'

A Python replacement copied into JavaScript inserts a literal \1; the reverse inserts a literal $1. Neither errors.

Escaping in replacements

A literal $ in a JavaScript or C# replacement is written $$. Java needs \$ instead, and PHP needs \$ when the dollar is followed by a digit. In Python $ has no special meaning, but use a raw string for the replacement or backslashes get interpreted twice. In Java, Matcher.quoteReplacement escapes a whole string safely.

This matters when replacing with user-supplied text: an unescaped $1 in that text silently injects a capture group. Use a function replacement when the value is not a literal you control.

Function replacements

Passing a function instead of a string is clearer than a dense pattern whenever the transformation has conditions:

// JavaScript — receives match, groups, offset
text.replace(/\b\d+\b/g, (n) => String(Number(n) * 2));

# Python — receives the match object
re.sub(r'\b\d+\b', lambda m: str(int(m.group()) * 2), text)

It also removes replacement-syntax escaping entirely, since the returned string is used literally.

First match or all

JavaScript replace changes only the first match unless the regex has g; replaceAll requires g and throws without it. Python re.sub replaces all by default and takes a count argument to limit. sed replaces once per line unless you add the g flag to the command. For a one-off edit of a document rather than code, a find and replace tool with a regex option does the same job without writing a script.

Test replacements against input containing multiple matches, overlapping candidates and zero matches. Zero matches should leave the string untouched — a replacement that returns an empty string instead usually means the wrong function was called.

Frequently asked questions

Why does my replacement insert a literal $1?

The language uses \1 rather than $1, or the string was copied from a different flavour.

How do I insert a literal dollar sign?

Use $$ in JavaScript and C#. In Java write \$, and in PHP escape it as \$ when a digit follows. In Python a $ in the replacement needs no escaping.

Why does replace only change the first match?

The regex lacks the g flag in JavaScript. Python replaces all by default.