我只是想从任何可能的字符串中创建一个正则表达式。
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
有内置的方法吗?如果不是,人们用什么?Ruby有RegExp.escape。我觉得我不需要写我自己的,必须有一些标准的东西。
我只是想从任何可能的字符串中创建一个正则表达式。
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
有内置的方法吗?如果不是,人们用什么?Ruby有RegExp.escape。我觉得我不需要写我自己的,必须有一些标准的东西。
当前回答
刚刚发布了一个基于RegExp.escape shim的regex转义要点,而RegExp.escape shim又是基于被拒绝的RegExp.escape提议的。看起来大致相当于公认的答案,除了它没有转义-字符,根据我的手动测试,这似乎实际上是好的。
撰写本文时的主要内容:
const syntaxChars = /[\^$\\.*+?()[\]{}|]/g
/**
* Escapes all special special regex characters in a given string
* so that it can be passed to `new RegExp(escaped, ...)` to match all given
* characters literally.
*
* inspired by https://github.com/es-shims/regexp.escape/blob/master/implementation.js
*
* @param {string} s
*/
export function escape(s) {
return s.replace(syntaxChars, '\\$&')
}
其他回答
这是长久之计。
function regExpEscapeFuture(literal_string) {
return literal_string.replace(/[^A-Za-z0-9_]/g, '\\$&');
}
在另一个答案中链接的函数是不够的。它不能转义^或$(字符串的开始和结束),或-,在字符组中用于范围。
使用这个函数:
function escapeRegex(string) {
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
}
虽然乍一看似乎没有必要,但转义-(以及^)使函数适合转义插入字符类以及正则表达式体中的字符。
转义/使函数适合转义在JavaScript正则表达式文字中使用的字符,以供以后计算。
由于转义它们都没有任何缺点,因此转义以覆盖更广泛的用例是有意义的。
是的,这不是标准JavaScript的一部分,这是一个令人失望的失败。
这里的大多数表达式都解决单个特定的用例。
这没关系,但我更喜欢“总是有效”的方法。
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) : '') + ')');
过去和将来只有12个元字符需要转义 被认为是字面上的
对转义字符串做什么并不重要,插入到平衡的正则表达式包装器或追加。没关系。
字符串替换使用这个吗
var escaped_string = oldstring.replace(/[\\^$.|?*+()[{]/g, '\\$&');
另一种(更安全的)方法是使用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');