1

如果我/[\w-+]/在 Chrome 控制台中输入,它会接受它。我得到了一个正则表达式对象,我可以像往常一样使用它来测试字符串。但如果我输入/[\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 文档说启用了u一些 Unicode 功能,但我没有看到任何关于它如何影响字符类中的范围的信息。

4

2 回答 2

4

RegExp 字符集中连字符减号(您的标准键盘破折号)表示它分隔的两个字符之间的字符代码范围。例外情况是当它被转义 ( \-) 或当它不分隔两个字符时,因为它要么是类的最后一个字符,要么是第一个字符(在反转类的可选插入符号之后)。

字符范围的三个示例:一个简单示例、一个高级示例和一个错误:

  • [a-z]非常简单,因为它按照我们期望的方式工作,尽管这实际上是因为字符代码恰好是连续的。另一种写法是[\x61-\x7a]
  • [!-~]一点也不简单,至少在您查看字符映射并了解这!是第一个可打印的 ASCII 字符并且~是最后一个(“低 ASCII”)之前,所以这是一种说法“所有可打印的低 ASCII 字符”它相当于[\x21-\x7e]
  • [A-z]里面有一个开关盒。您可能不喜欢这个范围接受六个非字母字符的事实(即[\x41-\x7a]

ASCII 表


现在让我们检查一下您的/[\w-+]/uRegex101 正则表达式是否有更多信息错误:“您无法使用速记转义序列创建范围”

由于\w它本身不是一个字符(而是一个字符的集合),因此必须按字面意思理解相邻的破折号,否则就是一个错误。当您使用触发/u 标志fullUnicode调用它时,您会进入更严格的模式,因此会出现错误。

"foo".match(/[\w-+]/u)我在 Firefox 64.0 中得到的错误是:

SyntaxError:字符类转义不能用于正则表达式的类范围

这比您得到的错误信息略多,因为它实际上告诉您问题出在转义上(尽管不是问题的原因)。

根据ECMAScript 2015 的RegExBuiltinExec()逻辑

  1. 如果fullUnicodetrue,则
    1. e输入字符列表的索引,从S派生,由matcher 匹配。令eUTFS中对应于Input元素e处的字符的最小索引。如果e大于或等于Input的长度,则eUTFS中的代码单元数。
    2. e成为eUTF

这似乎是在明确构建自己的范围解析逻辑。


解决方案是要么逃避你的连字符减号,要么把它放在最后(或第一个):

/[\w\-+]/u/[\w+-]/u/[-\w+]/u。我个人总是把它放在最后。

于 2019-01-15T20:37:04.743 回答
4

对此有一份报告:V8 实现:字符类范围中的 unicode 属性转义行为是否有意与其他类不同?.


我查看了 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

21.2.2.15.1 步骤 1。

如果A不包含恰好一个字符或B不包含恰好一个字符,则抛出SyntaxError异常。

于 2019-01-15T21:13:53.223 回答