如果我在Chrome控制台中输入/[\w-+]/
,它将接受它。我得到了一个正则表达式对象,可以像往常一样用来测试字符串。但是,如果我输入/[\w-+]/u
,它会显示VM112:1 Uncaught SyntaxError: Invalid regular expression: /[\w-+]/: Invalid character class
。
在Firefox中,/[\w-+]/
可以正常工作,但是如果我在控制台中键入/[\w-+]/u
,则它会转到下一行,就像我键入了不完整的语句一样。如果我尝试通过运行eval('/[\w-+]/u')
来强制它创建正则表达式,它将告诉我SyntaxError: invalid range in character class
。
为什么u
标志会使正则表达式无效? MDN RegExp documentation说u
启用了一些Unicode功能,但是我没有看到有关它如何影响字符类范围的信息。
答案 0 :(得分:3)
在RegExp character set中,hyphen-minus字符(您的标准键盘破折号)表示它分隔的两个字符之间的字符代码范围。例外情况是它被转义(\-
)或不分隔两个字符,因为它是该类的最后一个字符或它是第一个字符(在可选的插入符之后,反转了该类)。 / p>
三个字符范围示例:一个简单示例,一个高级示例和一个错误:
[a-z]
非常简单,因为它按照我们期望的方式工作,尽管实际上这是因为字符代码碰巧是顺序的。另一种写法是[\x61-\x7a]
[!-~]
一点都不简单,至少直到您查看一个字符映射表并了解到!
是第一个可打印的ASCII字符,而~
是最后一个( ASCII”),因此这是一种表示“所有可打印的较低ASCII字符”的方式,它等效于[\x21-\x7e]
[A-z]
的大小写已更改。您可能不喜欢这个范围接受六个非字母字符([\x41-\x7a]
)的事实现在,让我们检查一下/[\w-+]/u
的正则表达式Regex101有一个更有用的错误:“您不能使用简写转义序列创建范围”
由于\w
本身不是字符(而是字符的集合),所以必须在字面上取一个相邻的破折号,否则必须输入错误。当您使用/u
flag调用它来触发fullUnicode
时,将进入更严格的模式,因此会出现错误。
我在Firefox 64.0中从"foo".match(/[\w-+]/u)
得到的错误是:
SyntaxError:字符类转义不能在正则表达式的类范围内使用
这比您得到的错误信息多,因为它实际上告诉您问题出在转义上(尽管不是为什么这是问题)。
根据ECMAScript 2015's RegExBuiltinExec()
logic:
- 如果 fullUnicode 为 true ,则
- e 是从 S 派生的 Input 字符列表的索引,由 matcher 匹配。假设 eUTF 是 S 中与 Input 的元素 e 处的字符相对应的最小索引。如果 e 大于或等于 Input 的长度,则 eUTF 是 S中的代码单位数。
- 让 e 为 eUTF 。
这似乎是在明确建立自己的范围解析逻辑。
解决方案是逃避连字符减号或将其放在最后(或第一个):
/[\w\-+]/u
或/[\w+-]/u
或/[-\w+]/u
。我个人总是把它放在最后。
答案 1 :(得分:3)
我查看了V8源代码(regexp-parser.cc),发现了这一点:
if (is_class_1 || is_class_2) {
// Either end is an escaped character class. Treat the '-' verbatim.
if (unicode()) {
// ES2015 21.2.2.15.1 step 1.
return ReportError(CStrVector(kRangeInvalid));
}
kRangeInvalid
是包含Invalid character class
的常量。
如果
A
不包含一个字符,或者B
不包含一个字符 正好一个字符,则抛出SyntaxError
异常。