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

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

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


当前回答

XRegExp有一个转义函数:

XRegExp.escape(“逃?< >。'); // -> '已转义\?\ < \ >。”

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

其他回答

这是长久之计。

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

在https://github.com/benjamingr/RexExp.escape/上有一个RegExp.escape的ES7提议,在https://github.com/ljharb/regexp.escape上有一个polyfill可用。

其他答案中的函数对于转义整个正则表达式来说是多余的(它们对于转义正则表达式中稍后将连接到更大的regexp的部分可能有用)。

如果转义整个regexp并使用它,则引用独立的元字符(。, ?, +, *, ^, $, |, \) 或开始 ((, [, {) 是你所需要的:

String.prototype.regexEscape = function regexEscape() {
  return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};

是的,JavaScript没有这样的内置函数是令人失望的。

与其只转义字符,否则会导致正则表达式中的问题(例如:黑名单),不如考虑使用白名单。这样每个字符都被认为是有污点的,除非它匹配。

对于本例,假设有以下表达式:

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

白名单包括字母、数字和空格:

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

返回:

"be \|\| \! be"

这可能会转义不需要的字符,但这不会妨碍您的表达(可能会有一些小的时间损失-但为了安全起见,这是值得的)。

我借用了上面bobince的答案,创建了一个带标签的模板函数,用于创建RegExp,其中部分值被转义,部分值不被转义。

regex-escaped.js

RegExp.escape = text => text.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); RegExp.escaped = flags => function (regexStrings, ...escaped) { const source = regexStrings .map((s, i) => // escaped[i] will be undefined for the last value of s escaped[i] === undefined ? s : s + RegExp.escape(escaped[i].toString()) ) .join(''); return new RegExp(source, flags); }; function capitalizeFirstUserInputCaseInsensitiveMatch(text, userInput) { const [, before, match, after ] = RegExp.escaped('i')`^((?:(?!${userInput}).)*)(${userInput})?(.*)$`.exec(text); return `${before}${match.toUpperCase()}${after}`; } const text = 'hello (world)'; const userInput = 'lo (wor'; console.log(capitalizeFirstUserInputCaseInsensitiveMatch(text, userInput));

对于TypeScript的粉丝们…

global.d.ts

interface RegExpConstructor {
  /** Escapes a string so that it can be used as a literal within a `RegExp`. */
  escape(text: string): string;

  /**
   * Returns a tagged template function that creates `RegExp` with its template values escaped.
   *
   * This can be useful when using a `RegExp` to search with user input.
   *
   * @param flags The flags to apply to the `RegExp`.
   *
   * @example
   *
   * function capitalizeFirstUserInputCaseInsensitiveMatch(text: string, userInput: string) {
   *   const [, before, match, after ] =
   *     RegExp.escaped('i')`^((?:(?!${userInput}).)*)(${userInput})?(.*)$`.exec(text);
   *
   *   return `${before}${match.toUpperCase()}${after}`;
   * }
   */
  escaped(flags?: string): (regexStrings: TemplateStringsArray, ...escapedVals: Array<string | number>) => RegExp;
}