在RegExp 字符集中,连字符减号(您的标准键盘破折号)表示它分隔的两个字符之间的字符代码范围。例外情况是当它被转义 ( \-
) 或当它不分隔两个字符时,因为它要么是类的最后一个字符,要么是第一个字符(在反转类的可选插入符号之后)。
字符范围的三个示例:一个简单示例、一个高级示例和一个错误:
[a-z]
非常简单,因为它按照我们期望的方式工作,尽管这实际上是因为字符代码恰好是连续的。另一种写法是[\x61-\x7a]
[!-~]
一点也不简单,至少在您查看字符映射并了解这!
是第一个可打印的 ASCII 字符并且~
是最后一个(“低 ASCII”)之前,所以这是一种说法“所有可打印的低 ASCII 字符”它相当于[\x21-\x7e]
[A-z]
里面有一个开关盒。您可能不喜欢这个范围接受六个非字母字符的事实(即[\x41-\x7a]
)

现在让我们检查一下您的/[\w-+]/u
Regex101 正则表达式是否有更多信息错误:“您无法使用速记转义序列创建范围”
由于\w
它本身不是一个字符(而是一个字符的集合),因此必须按字面意思理解相邻的破折号,否则就是一个错误。当您使用触发/u
标志fullUnicode
调用它时,您会进入更严格的模式,因此会出现错误。
"foo".match(/[\w-+]/u)
我在 Firefox 64.0 中得到的错误是:
SyntaxError:字符类转义不能用于正则表达式的类范围
这比您得到的错误信息略多,因为它实际上告诉您问题出在转义上(尽管不是问题的原因)。
根据ECMAScript 2015 的RegExBuiltinExec()
逻辑:
- 如果fullUnicode为true,则
- e是输入字符列表的索引,从S派生,由matcher 匹配。令eUTF 为S中对应于Input元素e处的字符的最小索引。如果e大于或等于Input的长度,则eUTF是S中的代码单元数。
- 让e成为eUTF。
这似乎是在明确构建自己的范围解析逻辑。
解决方案是要么逃避你的连字符减号,要么把它放在最后(或第一个):
/[\w\-+]/u
或/[\w+-]/u
或/[-\w+]/u
。我个人总是把它放在最后。