我只想从任何可能的字符串中创建一个正则表达式。
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
有内置的方法吗?如果没有,人们会使用什么?红宝石有RegExp.escape
。我觉得我不需要自己写东西,那里肯定有一些标准。谢谢!
我只想从任何可能的字符串中创建一个正则表达式。
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
有内置的方法吗?如果没有,人们会使用什么?红宝石有RegExp.escape
。我觉得我不需要自己写东西,那里肯定有一些标准。谢谢!
Answers:
上面链接的功能不足。它无法转义^
或$
(字符串的开头和结尾)或-
,这在字符组中用于范围。
使用此功能:
function escapeRegex(string) {
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
乍看起来似乎没有必要,但转义-
(以及^
)使该函数适合于转义要插入字符类和正则表达式主体的字符。
转义/
使该函数适合转义要在JS正则表达式文字中使用的字符,以供以后评估。
由于逃避任何一个都没有不利之处,因此有理由逃避以涵盖更广泛的用例。
是的,如果它不是标准JavaScript的一部分,这是令人失望的。
/
可言
quotemeta
(\Q
),Python re.escape
,PHP preg_quote
,Ruby Regexp.quote
...
var e = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
,然后将函数设为。return s.replace(e, '\\$&');
这样,您只需实例化RegExp一次。
RegExp.escape
的实现与您的实现不同,会发生什么情况?不将此功能附加到任何东西上会更好吗?
对于使用lodash的任何人,从v3.0.0开始,都内置了_.escapeRegExp函数:
_.escapeRegExp('[lodash](https://lodash.com/)');
// → '\[lodash\]\(https:\/\/lodash\.com\/\)'
escapeRegExp
功能。
这里的大多数表达式解决单个特定的用例。
没关系,但我更喜欢“始终有效”的方法。
function regExpEscape(literal_string) {
return literal_string.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}
对于正则表达式中的以下任何一种用法,这将“完全转义”文字字符串:
new RegExp(regExpEscape(str))
new RegExp('[' + regExpEscape(str) + ']')
new RegExp('x{1,' + regExpEscape(str) + '}')
涵盖的特殊字符:
-
:在字符类中创建字符范围。[
/ ]
:开始/结束字符类。{
/ }
:开始/结束一个数字说明符。(
/ )
:开始/结束组。*
/ +
/ ?
:指定重复类型。.
:匹配任何字符。\
:转义字符,然后启动实体。^
:指定匹配区域的开始,并否定字符类中的匹配。$
:指定匹配区域的结尾。|
:指定交替。#
:以自由间距模式指定注释。\s
:在自由间距模式下被忽略。,
:分隔数值说明符中的值。/
:开始或结束表达式。:
:完成特殊的组类型以及Perl样式的字符类的一部分。!
:否定零宽度组。<
/ =
:零宽度组规格的一部分。笔记:
/
在任何形式的表达中都不是必须的。但是,它可以防止有人(颤抖)这样做eval("/" + pattern + "/");
。,
确保如果字符串在数字说明符中应为整数,则它将正确地引起RegExp编译错误,而不是无提示地编译错误。#
,\s
不需要在JavaScript中进行转义,而是在许多其他方式中进行转义。如果正则表达式以后将传递给另一个程序,它们将在此处转义。如果您还需要对正则表达式进行将来的校对,以防可能增加JavaScript regex引擎功能,则建议使用更多偏执狂:
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) : '') + ')');
/
不需要它的转义[...]
字符类。
Mozilla开发人员网络正则表达式指南提供了以下转义功能:
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
=
不再包含。
在jQueryUI的自动完成小部件(版本1.9.1)中,他们使用略有不同的正则表达式(第6753行),这是将正则表达式与@bobince方法结合使用。
RegExp.escape = function( value ) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
,
(不是元字符),#
而空格仅在自由间距模式下才重要(JavaScript不支持)。但是,他们确实正确地避免了不使用正斜杠。
$.ui.autocomplete.escapeRegex(myString)
。
没有什么可以阻止您仅转义每个非字母数字字符的:
usersString.replace(/(?=\W)/g, '\\');
在执行操作时,您会失去一定程度的可读性,re.toString()
但会获得很多简化(和安全性)。
根据ECMA-262,在一方面,正则表达式“的语法的字符”总是非字母数字,使得结果是安全的,和特殊的转义序列(\d
,\w
,\n
)总是字母数字,使得没有假控制逃逸会产生。
.replace(/[^\w]/g, '\\$&')
将以相同的方式工作。
new RegExp('🍎'.replace(/(?=\W)/g, '\\'), 'u')
抛出异常是因为分别\W
匹配代理对的每个代码单元,从而导致无效的转义码。
.replace(/\W/g, "\\$&");
有一个ES7提案RegExp.escape在https://github.com/benjamingr/RexExp.escape/,与可用填充工具https://github.com/ljharb/regexp.escape。
这是一个较短的版本。
RegExp.escape = function(s) {
return s.replace(/[$-\/?[-^{|}]/g, '\\$&');
}
这包括非元字符%
,&
,'
,和,
,但JavaScript的正则表达式规范允许这样做。
.
是错过了。和()
。或不?[-^
很奇怪 我不记得那里有什么。
XRegExp具有转义功能:
XRegExp.escape('Escaped? <.>');
// -> 'Escaped\?\ <\.>'
有关更多信息:http : //xregexp.com/api/#escape
不仅要转义会导致正则表达式出现问题的字符(例如:黑名单),还不考虑使用白名单。这样,除非每个字符都匹配,否则将被视为已污染。
对于此示例,假定以下表达式:
RegExp.escape('be || ! be');
这会将字母,数字和空格列入白名单:
RegExp.escape = function (string) {
return string.replace(/([^\w\d\s])/gi, '\\$1');
}
返回值:
"be \|\| \! be"
这可以使不需要转义的字符转义,但这不会妨碍您的表情(也许会受到一些时间上的惩罚-但出于安全考虑,这是值得的)。
其他答案中的函数对于转义整个正则表达式是过大的(它们对于转义正则表达式的某些部分可能有用,这些正则表达式随后将被连接成更大的正则表达式)。
如果你逃避整个正则表达式,并用它完成后,报价是要么独立的元字符(.
,?
,+
,*
,^
,$
,|
,\
),或者开始做某件事((
,[
,{
)是所有你需要:
String.prototype.regexEscape = function regexEscape() {
return this.replace(/[.?+*^$|({[\\]/g, '\\$&');
};
是的,令人失望的是,JavaScript没有这样的内置函数。
(text)next
并将其插入:(?:
+ input + )
。您的方法将给出(?:\(text)next)
无法编译的结果字符串。请注意,这是相当合理的插入,而不是像re\
+输入+ 这样的疯狂输入re
(在这种情况下,程序员可能因做愚蠢的行为而受到指责)
\
应该转义,因为您的正则表达式将\w
保持不变。另外,JavaScript似乎不允许尾随)
,至少这是Firefox抛出错误的原因。
)
另一种(更安全)的方法是使用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');
曾经有过并且将永远有12个元字符需要转义
才能视为文字。
无关紧要的是,将转义的字符串插入平衡的
regex包装器中并附加后,该字符串做什么都没有关系。
使用此字符串替换
var escaped_string = oldstring.replace( /[\\^$.|?*+()[{]/g, '\\$&' );
]
呢?
RegExp.escape
目前正在研究的优秀人才,非常欢迎任何认为自己有宝贵意见的人做出贡献。core-js和其他polyfills提供了它。