Regex.IsMatch( "foo", "[\U00010000-\U0010FFFF]" )
抛出:System.ArgumentException:以相反的顺序解析“[-]” - [xy] 范围。
查看 \U00010000 和 \U0010FFF 的十六进制值,我得到:第一个字符为 0xd800 0xdc00,第二个字符为 0xdbff 0xdfff。
所以我想我真的有一个问题。为什么用 \U 形成的 Unicode 字符在字符串中分成两个字符?
Regex.IsMatch( "foo", "[\U00010000-\U0010FFFF]" )
抛出:System.ArgumentException:以相反的顺序解析“[-]” - [xy] 范围。
查看 \U00010000 和 \U0010FFF 的十六进制值,我得到:第一个字符为 0xd800 0xdc00,第二个字符为 0xdbff 0xdfff。
所以我想我真的有一个问题。为什么用 \U 形成的 Unicode 字符在字符串中分成两个字符?
他们是代理对。看看这些值——它们超过了 65535。一个字符只是一个 16 位的值。您将如何仅用 16 位表示 65536?
不幸的是,从文档中不清楚 .NET 中的正则表达式引擎如何(或是否)处理不在基本多语言平面中的字符。(正则表达式文档中的 \uxxxx 模式仅涵盖 0-65535,就像将 \uxxxx 作为 C# 转义序列一样。)
您真正的正则表达式是否更大,或者您实际上只是想查看其中是否有任何非 BMP 字符?
为了使用 .Net 正则表达式引擎解决此类问题,我使用了以下技巧:
"[\U010000-\U10FFFF]"
替换为[\uD800-\uDBFF][\uDC00-\uDFFF]
这背后的想法是,当 .Net 正则表达式处理代码单元而不是代码点时,我们将代理范围作为常规字符提供给它。也可以通过使用边缘来指定更窄的范围,例如:[\U011DEF-\U013E07]
与(?:\uD807[\uDDEF-\uDFFF])|(?:[\uD808-\uD80E][\uDC00-\uDFFF])|(?:\uD80F[\uDC00-uDE07])
它更难阅读和操作,也不是那么灵活,但仍然适合作为解决方法。
@乔恩斯基特
所以你告诉我的是,没有办法使用 .net 中的正则表达式工具来匹配 utf-16 范围之外的字符?
完整的正则表达式是:
^(\u0009|[\u0020-\u007E]|\u0085|[\u00A0-\uD7FF]|[\uE000-\uFFFD]|[\U00010000-\U0010FFFF])+$
我正在尝试检查字符串是否仅包含 yaml 文档定义为可打印 Unicode 字符的内容。