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

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

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


当前回答

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

其他回答

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

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

在另一个答案中链接的函数是不够的。它不能转义^或$(字符串的开始和结束),或-,在字符组中用于范围。

使用这个函数:

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

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

转义/使函数适合转义在JavaScript正则表达式文字中使用的字符,以供以后计算。

由于转义它们都没有任何缺点,因此转义以覆盖更广泛的用例是有意义的。

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

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

在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

or

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这个选项的描述。该逻辑基于返回regexp .escape || implementation;,其中实现包含上面使用的regexp。


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

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

这没关系,但我更喜欢“总是有效”的方法。

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正则表达式引擎中执行。

涉及的特殊字符:

-: Creates a character range in a character class. [ / ]: Starts / ends a character class. { / }: Starts / ends a numeration specifier. ( / ): Starts / ends a group. * / + / ?: Specifies repetition type. .: Matches any character. \: Escapes characters, and starts entities. ^: Specifies start of matching zone, and negates matching in a character class. $: Specifies end of matching zone. |: Specifies alternation. #: Specifies comment in free spacing mode. \s: Ignored in free spacing mode. ,: Separates values in numeration specifier. /: Starts or ends expression. :: Completes special group types, and part of Perl-style character classes. !: Negates zero-width group. < / =: Part of zero-width group specifications.

注:

/在任何类型的正则表达式中都不是严格必要的。但是,如果有人(不寒而栗)执行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中应该编译得很好,但在其他类型中就不行。如果打算传递给另一个flavor,则应该单独检查s === "的空大小写,如下所示:

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