.net 代理项对检测失败
我在F#中做一个小项目,涉及将现有的C#代码移植到F#,我似乎遇到了两种语言之间正则表达式处理方式的差异(我发布这篇文章是希望发现我只是做错了什么) 这个小函数使用正则表达式技巧简单地检测代理项对。以下是当前的实现:.net 代理项对检测失败,.net,regex,unicode,f#,surrogate-pairs,.net,Regex,Unicode,F#,Surrogate Pairs,我在F#中做一个小项目,涉及将现有的C#代码移植到F#,我似乎遇到了两种语言之间正则表达式处理方式的差异(我发布这篇文章是希望发现我只是做错了什么) 这个小函数使用正则表达式技巧简单地检测代理项对。以下是当前的实现: let isSurrogatePair input = Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]") 如果我对一个已知的代理项对执行它,如下所示: let result = isSurrogatePair "
let isSurrogatePair input =
Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
如果我对一个已知的代理项对执行它,如下所示:
let result = isSurrogatePair "There appears to be a bug in how F# encodes escaped Unicode characters.
Here's from the F# Interactive (note the last two results):
> "\uD500".[0] |> uint16 ;;
val it : uint16 = 54528us
> "\uD700".[0] |> uint16 ;;
val it : uint16 = 55040us
> "\uD800".[0] |> uint16 ;;
val it : uint16 = 65533us
> "\uD900".[0] |> uint16 ;;
val it : uint16 = 65533us
let result=isSurrogatePair”F#编码转义Unicode字符的方式似乎存在错误。
以下是F#Interactive(注意最后两个结果):
幸运的是,此解决方案可以工作:
let isSurrogatePair input =
let chrToStr code = new System.String( [| char code |] )
let regex = "[" + (chrToStr 0xD800) + "-" + (chrToStr 0xDBFF) + "][" + (chrToStr 0xDC00) + "-" + (chrToStr 0xDFFF) + "]"
Regex.IsMatch(input, regex)
基于这一发现,我可以构建一个isSurrogatePair
的修正版(或者说变通版):
Regex.IsMatch(input, "[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]")
// or
Regex.IsMatch(input, @"[\uD800-\uDBFF][\uDC00-\uDFFF]")
此版本正确返回您输入的true
我刚刚在GitHub上提交了这个问题:似乎这是一个合法的F#bug,没有任何争议。只是想建议一些替代解决方案
不要将问题字符嵌入字符串本身,请使用正则表达式的常规unicode支持指定它们。匹配unicode代码点XXXX
的正则表达式模式是\uxxx
,因此只需转义反斜杠或使用逐字字符串:
// high surrogate followed by low surrogate
Regex.IsMatch(input, @"(\p{IsHighSurrogates}|\p{IsHighPrivateUseSurrogates})\p{IsLowSurrogates}")
对unicode块使用内置正则表达式支持:
// 2 characters, each of which is half of a surrogate pair
// (maybe could give false-positive if both are, e.g. low-surrogates)
Regex.IsMatch(input, @"\p{Cs}{2}")
或财产
对于后代:最新版本的F#解决了这个问题,文字不再显示这种编码问题。
// 2 characters, each of which is half of a surrogate pair
// (maybe could give false-positive if both are, e.g. low-surrogates)
Regex.IsMatch(input, @"\p{Cs}{2}")