为什么这种否定前瞻 Unicode 正则表达式在直接匹配时在 JavaScript 中不起作用?

Why does this negative lookahead Unicode regex not work in JavaScript when direct match does?

我正在尝试验证最终将在 URL 中使用的字符串的文件名或目录部分,并希望拒绝非 Unicode 和其他字符,正则表达式返回空字节。

给定此字符串作为输入:

զվարճ?անք9879#jhkjhkhl!kjljlkjlkjj()+======\_ew.html

/(?![\p{L}]|[\p{N}]|[\._-~])/gu

JavaScript returns 更正无效字符匹配,但为每个匹配的字符而不是完整字符选择一个空字节。

如果我 运行 相反,并尝试匹配可以的字符而不是不可以的字符:

/[\p{L}]|[\p{N}]|[\._-~]/gu

JavaScript returns 按预期匹配并选择每个有效字符,没有空字节匹配。

每个模式都有 /u 标志。我不明白行为上的差异。在最新的 Chrome(截至 post 日期更新 100)、Safari 和 Firefox 中对此进行了测试,它们的行为都相同。

第一个正则表达式是否缺少某些标志或运算符,或者这是 JavaScript 错误/限制?

你不是匹配,只是断言。您可以在断言之后立即匹配单个字符,并将交替捆绑到单个字符 class:

(?![\p{L}\p{N}._-~]).

Regex 101 demo

或者您可以使用以 [^

开头的取反字符 class 匹配 1 次或多次
[^\p{L}\p{N}._-~]+

Regex 101 demo

注意字符class_-~中的这部分表示一个范围而不是字符_-~

如果要匹配-字符,可以将其转义或者放在字符class.

的开头或结尾