JavaScript 中有 RegExp.escape 函数吗?

IT技术 javascript regex
2021-01-02 23:53:07

我只想从任何可能的字符串中创建一个正则表达式。

var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);

有没有内置的方法?如果不是,人们用什么?Ruby有RegExp.escape我不觉得我需要自己写,那里必须有一些标准的东西。

6个回答

另一个答案中链接的功能不足。它无法转义^or $(字符串的开头和结尾)或-,它在字符组中用于范围。

使用这个功能:

function escapeRegex(string) {
    return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

虽然乍一看似乎没有必要,但转义-(以及^)使该函数适合转义要插入字符类以及正则表达式主体的字符。

转义/使该函数适用于转义要在 JavaScript 正则表达式文字中使用的字符以供以后评估。

由于逃避它们中的任何一个都没有缺点,因此逃避以涵盖更广泛的用例是有意义的。

是的,这不是标准 JavaScript 的一部分,这是一个令人失望的失败。

bobince 不在乎 eslint 的意见
2021-02-20 23:53:07
如果你打算在循环中使用这个函数,最好将 RegExp 对象设为它自己的变量var e = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;,然后你的函数就是return s.replace(e, '\\$&');这样你只实例化 RegExp 一次。
2021-02-26 23:53:07
但也许您想转义字符以将它们放在字符范围内。IMO 最好无害地过度逃避,而不是逃避不足并在特殊情况下引起问题。FWIW 个人我宁愿在这里明确地看到角色;我们不是在玩代码高尔夫。
2021-03-04 23:53:07
其实,我们不需要逃避/可言
2021-03-05 23:53:07
@Paul:Perl quotemeta( \Q)、Python re.escape、PHP preg_quote、Ruby Regexp.quote...
2021-03-05 23:53:07

对于任何使用 Lodash 的人,从 v3.0.0开始,内置了一个_.escapeRegExp函数:

_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'

而且,如果您不想需要完整的 Lodash 库,您可能需要该功能

@RobEvans 我的回答以“对于任何使用 lodash 的人”开头,我什至提到您可以需要escapeRegExp功能。
2021-02-07 23:53:07
@gustavohenke 抱歉,我应该更清楚一些,我将链接到的module包含在您的“只是那个功能”中,这就是我正在评论的内容。如果你看一看,它有很多代码,它们实际上应该是一个带有单个正则表达式的单个函数。同意,如果您已经在使用 lodash,那么使用它是有意义的,否则请使用其他答案。抱歉,评论不清楚。
2021-02-08 23:53:07
@maddob 我看不到您提到的 \x3:我的转义字符串看起来不错,正是我所期望的
2021-02-28 23:53:07
甚至还有一个这样的 npm 包!npmjs.com/package/lodash.escaperegexp
2021-03-02 23:53:07
这会导入大量代码,对于这么简单的事情,这些代码实际上并不需要存在。使用 bobince 的答案......对我有用,而且它比 lodash 版本要加载的字节少得多!
2021-03-06 23:53:07

这里的大多数表达式都解决了单个特定用例。

没关系,但我更喜欢“始终有效”的方法。

function regExpEscape(literal_string) {
    return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

这将“完全转义”正则表达式中以下任何用途的文字字符串:

  • 插入正则表达式。例如new RegExp(regExpEscape(str))
  • 插入字符类。例如new RegExp('[' + regExpEscape(str) + ']')
  • 插入整数计数说明符。例如new RegExp('x{1,' + regExpEscape(str) + '}')
  • 在非 JavaScript 正则表达式引擎中执行。

涵盖的特殊字符:

  • -: 在字符类中创建字符范围。
  • [/ ]:开始/结束一个字符类。
  • {/ }:开始/结束一个数字说明符。
  • (/ ):开始/结束一个组。
  • */ +/ ?:指定重复类型。
  • .: 匹配任何字符。
  • \: 转义字符,并启动实体。
  • ^: 指定匹配区域的开始,并否定字符类中的匹配。
  • $: 指定匹配区域的结束。
  • |: 指定交替。
  • #: 在自由间距模式下指定注释。
  • \s: 在自由间距模式下忽略。
  • ,: 分隔数值说明符中的值。
  • /: 开始或结束表达式。
  • :: 完成特殊的组类型,以及部分 Perl 风格的字符类。
  • !:否定零宽度组。
  • </ =: 零宽度组规范的一部分。

笔记:

  • /在任何风格的正则表达式中都不是绝对必要的。但是,如果有人(不寒而栗)这样做,它会提供保护eval("/" + pattern + "/");
  • , 确保如果字符串是数字说明符中的整数,它将正确地导致 RegExp 编译错误而不是静默编译错误。
  • #, 并且\s不需要在 JavaScript 中转义,但可以在许多其他风格中进行。它们在此处被转义,以防正则表达式稍后被传递给另一个程序。

如果您还需要针对 JavaScript 正则表达式引擎功能的潜在添加来验证正则表达式的未来,我建议使用更偏执的:

function regExpEscapeFuture(literal_string) {
    return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}

除了明确保证不会用于未来正则表达式风格的语法的字符外,此函数会转义每个字符。


对于真正热衷于卫生的人,请考虑以下极端情况:

var s = '';
new RegExp('(choice1|choice2|' + regExpEscape(s) + ')');

在 JavaScript 中应该可以很好地编译,但在其他一些风格中则不能。如果打算传递给另一种风格,s === ''则应独立检查的空情况,如下所示:

var s = '';
new RegExp('(choice1|choice2' + (s ? '|' + regExpEscape(s) : '') + ')');
“完成特殊的组类型和 Perl 风格的字符类的一部分” - 在 javascript 中似乎不可用。“否定零宽度组,零宽度组规范的一部分” - 字符串中永远不会有组。
2021-02-12 23:53:07
/不需要它的转义[...]字符类。
2021-02-23 23:53:07
其中大部分不需要转义。“在字符类中创建字符范围” - 您永远不会在字符串内的字符类中。“在自由间距模式下指定注释,在自由间距模式下忽略” - javascript 不支持。“在数字说明符中分隔值” - 您永远不会在字符串内的数字说明符中。此外,您不能在命名规范中写入任意文本。“开始或结束表达” - 无需转义。Eval 不是一个案例,因为它需要更多的转义。[将在下一个评论中继续]
2021-02-25 23:53:07
@Qwertiy 这些额外转义的原因是为了消除在某些用例中可能导致问题的边缘情况。例如,此函数的用户可能希望将转义的正则表达式字符串作为组的一部分插入到另一个正则表达式中,或者甚至用于除 Javascript 之外的另一种语言。该函数不会做出诸如“我永远不会成为角色类的一部分”之类的假设,因为它是通用的有关更多 YAGNI 方法,请参阅此处的任何其他答案。
2021-03-05 23:53:07
非常好。为什么 _ 没有逃脱?什么确保它以后可能不会成为正则表达式语法?
2021-03-08 23:53:07

Mozilla 开发者网络的正则表达式指南提供了这个转义函数:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
@DanDascalescu 你是对的。MDN 页面已更新,=不再包含在内。
2021-02-22 23:53:07

在 jQuery UI 的自动完成小部件(1.9.1 版)中,它们使用了稍微不同的正则表达式(第 6753 行),这里是结合bobince 方法的正则表达式

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
v1.12一样,ok!
2021-02-08 23:53:07
唯一的区别是它们转义,(不是元字符)#和空格,它们仅在自由间距模式下才重要(JavaScript 不支持)。然而,他们没有逃避正斜杠是正确的。
2021-02-11 23:53:07
lodash 也有这个,_。escapeRegExp 和npmjs.com/package/lodash.escaperegexp
2021-02-11 23:53:07
如果您想重用 jquery UI 的实现而不是在本地粘贴代码,请使用$.ui.autocomplete.escapeRegex(myString).
2021-02-13 23:53:07