Lodash escapeRegExp with Already Escaped Strings
Lodash's _.escapeRegExp function is designed to sanitize
strings by escaping special regular expression characters so they can be
safely passed into a RegExp constructor. However, when
passed a string that has already been escaped, the function does not
detect existing escape sequences. Instead, it treats the existing escape
characters—specifically the backslash (\)—as characters
that must also be escaped, resulting in double-escaped strings that may
break the intended regular expression pattern.
The Mechanism Behind
_.escapeRegExp
The internal implementation of Lodash's _.escapeRegExp
relies on a predefined list of regular expression characters that
require escaping. This list includes:
^, $, \, .,
*, +, ?, (,
), [, ], {,
}, and |.
The function uses a standard replacement mechanism that matches any of these characters globally and prepends a backslash to them:
const reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
const escapeRegExp = (string) => string.replace(reRegExpChar, '\\$&');Because the backslash character (\) is explicitly listed
in reRegExpChar, _.escapeRegExp escapes every
backslash it encounters without analyzing the surrounding syntax.
What Happens to Already Escaped Strings
If an input string contains an escaped regular expression sequence, the existing backslash is treated like any other special character and gets escaped again.
Consider the following example:
const _ = require('lodash');
// An already escaped string representing a literal dot
const preEscaped = '\\.';
const result = _.escapeRegExp(preEscaped);
console.log(result);
// Output: "\\\\\\."In string representation:
preEscapedcontains two characters:\and.._.escapeRegExpprocesses the string character by character.- The backslash
\matches the escape rule and becomes\\. - The dot
.matches the escape rule and becomes\.. - The combined result becomes
\\\..
When passed to new RegExp(result), the regex engine
interprets the first two backslashes as a literal backslash and the
remaining \. as a literal dot. Instead of searching for
just a dot (.), the pattern now searches for a backslash
followed by a dot (\.).
Why Lodash Does Not Prevent Double-Escaping
Lodash avoids inspecting whether a backslash is part of an existing escape sequence for performance and predictability reasons. Parsing regular expression context—such as determining if a backslash itself is being escaped or if it is escaping an invalid character—adds significant complexity and execution overhead. The utility is intentionally designed under the assumption that the input is raw, unescaped text.
How to Prevent Double-Escaping Issues
To prevent unexpected behavior when dealing with regular expressions:
- Pass Raw Strings Only: Ensure strings passed to
_.escapeRegExpare pure literal text before applying any regex formatting. - Avoid Pre-escaping: Do not manually escape inputs before passing them into utility functions.
- Unescape First (If Necessary): If processing
untrusted or mixed inputs that might already be escaped, strip the
leading backslashes before passing the string to
_.escapeRegExp, or use a custom unescaping parser tailored to your input format.