Javascript中是否有RegExp.escape函数?

时间:2010-08-24 22:22:33

标签: javascript regex

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

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

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

15 个答案:

答案 0 :(得分:477)

上面链接的功能不足。它无法转义^$(字符串的开头和结尾)或-,它们在字符组中用于范围。

使用此功能:

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

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

转义/使该函数适合转义在JS regex文字中用于以后eval的字符。

由于逃避其中任何一个都没有任何缺点,因此有必要逃避覆盖更广泛的用例。

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

答案 1 :(得分:86)

对于使用lodash的任何人,since v3.0.0内置_.escapeRegExp函数:

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

而且,如果您不想要完整的lodash库,则可能需要just that function

答案 2 :(得分:35)

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

没关系,但我更喜欢"总是有效的"方法

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

这将完全逃脱&#34;正则表达式中任何以下用法的文字字符串:

  • 插入正则表达式。例如。 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) : '') + ')');

答案 3 :(得分:20)

在jQueryUI的自动完成小部件(版本1.9.1)中,他们使用了一个略有不同的正则表达式(第6753行),这里是正则表达式与@bobince方法相结合。

RegExp.escape = function( value ) {
     return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}

答案 4 :(得分:16)

Mozilla Developer Network's Guide to Regular Expressions提供了这个转义功能:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

答案 5 :(得分:9)

https://github.com/benjamingr/RexExp.escape/处有一个针对RegExp.escape的ES7提案,并在https://github.com/ljharb/regexp.escape处提供了一个填充。

答案 6 :(得分:9)

没有什么可以阻止你逃避每个非字母数字字符:

usersString.replace(/(?=\W)/g, '\\');

您在执行re.toString()时失去了一定程度的可读性,但您获得了极大的简单性(和安全性)。

根据ECMA-262,一方面,正则表达式“语法字符”始终是非字母数字,因此结果是安全的,以及特殊的转义序列(\d\w\n)始终是字母数字,因此不会产生错误的控制转义。

答案 7 :(得分:5)

这是一个较短的版本。

RegExp.escape = function(s) {
    return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}

这包括%&',的非元字符,但JavaScript RegExp规范允许这样做。

答案 8 :(得分:2)

escapeRegExp = function(str) {
  if (str == null) return '';
  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};

答案 9 :(得分:2)

XRegExp有一个转义函数:

XRegExp.escape('Escaped? <.>'); // -> 'Escaped\?\ <\.>'

更多信息:http://xregexp.com/api/#escape

答案 10 :(得分:2)

为什么不考虑使用白名单,而不是仅仅转义会导致正则表达式出现问题的字符(例如:黑名单)。这样每个角色都被认为是污染的,除非它匹配。

对于此示例,假设以下表达式:

RegExp.escape('be || ! be');

这会将字母,数字和空格列入白名单:

RegExp.escape = function (string) {
    return string.replace(/([^\w\d\s])/gi, '\\$1');
}

返回:

"be \|\| \! be"

这可能会逃脱不需要逃脱的角色,但这并不妨碍你的表达(可能是一些小的时间惩罚 - 但为了安全起见,这是值得的。)

答案 11 :(得分:2)

https://github.com/benjamingr/RexExp.escape/有一个针对RegExp.escape的ES7提案,在https://github.com/ljharb/regexp.escape有一个polyfill。

基于被拒绝的ES提案的示例包括检查该属性是否已经存在,以防TC39退回其决定。


代码:

if (!Object.prototype.hasOwnProperty.call(RegExp, 'escape')) {
  RegExp.escape = function(string) {
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
    // https://github.com/benjamingr/RegExp.escape/issues/37
    return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  };
}

代码已缩小:

Object.prototype.hasOwnProperty.call(RegExp,"escape")||(RegExp.escape=function(e){return e.replace(/[.*+\-?^${}()|[\]\\]/g,"\\$&")});

// ...
var assert = require('assert');
 
var str = 'hello. how are you?';
var regex = new RegExp(RegExp.escape(str), 'g');
assert.equal(String(regex), '/hello\. how are you\?/g');

在以下位置还有一个npm模块: https://www.npmjs.com/package/regexp.escape


一个人可以安装并按以下方式使用它:


npm install regexp.escape

yarn add regexp.escape

var escape = require('regexp.escape');
var assert = require('assert');
 
var str = 'hello. how are you?';
var regex = new RegExp(escape(str), 'g');
assert.equal(String(regex), '/hello\. how are you\?/g');

在GitHub && NPM页面中,还描述了如何将shim / polyfill用于此选项。该逻辑基于return RegExp.escape || implementation;,其中实现包含上面使用的regexp。


NPM模块是一个额外的依赖项,但是它也使外部贡献者更容易识别添加到代码中的逻辑部分。 ¯\ (ツ)

答案 12 :(得分:0)

另一种(更安全)的方法是使用unicode转义格式\u{code}转义所有字符(而不仅仅是我们目前知道的一些特殊字符):

function escapeRegExp(text) {
    return Array.from(text)
           .map(char => `\\u{${char.charCodeAt(0).toString(16)}}`)
           .join('');
}

console.log(escapeRegExp('a.b')); // '\u{61}\u{2e}\u{62}'

请注意,您需要传递u标志才能使此方法起作用:

var expression = new RegExp(escapeRegExp(usersString), 'u');

答案 13 :(得分:0)

曾经有过并且将永远有12个需要转义的元字符
被视为文字。

插入已平衡的转义字符串无关紧要
正则表达式包装器,没有关系。

使用此字符串替换

var escaped_string = oldstring.replace( /[\\^$.|?*+()[{]/g, '\\$&' );

答案 14 :(得分:-1)

其他答案中的函数对于转义整个正则表达式来说是过度的(它们可能对转义正则表达式的部分非常有用,以后会连接成更大的正则表达式)。

如果您转义整个正则表达式并完成它,请引用独立的元字符(.?+*,{{1 }},^$|)或启动某些内容(\([)就是您所需要的:

{

是的,令人失望的是JavaScript没有像这样内置的功能。