代理对检测失败

Sve*_*sen 7 .net regex unicode f# surrogate-pairs

我正在研究F#中的一个小方面项目,其中涉及将现有的C#代码移植到F#,我似乎在两种语言之间处理正则表达式的方式有所不同(我发布这个以希望找到我是只是做错了什么).

这个次要功能只使用此处概述的正则表达式技巧来检测代理对.这是当前的实现:

let isSurrogatePair input =
    Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
Run Code Online (Sandbox Code Playgroud)

如果我然后针对已知的代理对执行它,如下所示:

let result = isSurrogatePair "?"
printfn "%b" result
Run Code Online (Sandbox Code Playgroud)

我进入false了FSI窗口.

如果我使用等效的C#:

public bool IsSurrogatePair(string input)
{
    return Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]");
}
Run Code Online (Sandbox Code Playgroud)

和相同的输入值,我(正确)true回来.

这是一个真正的问题吗?我只是在F#实现中做错了吗?

Fyo*_*kin 8

F#如何编码转义的Unicode字符似乎存在错误.
这是来自F#Interactive(注意最后两个结果):

> "\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
Run Code Online (Sandbox Code Playgroud)

幸运的是,这种解决方法有效:

> let s = new System.String( [| char 0xD800 |] )
s.[0] |> uint16
;;

val s : System.String = "?"
val it : uint16 = 55296us
Run Code Online (Sandbox Code Playgroud)

根据这一发现,我可以构建一个更正的(或者更确切地说是工作方式)版本isSurrogatePair:

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)
Run Code Online (Sandbox Code Playgroud)

此版本正确返回true您的输入.

我刚刚在GitHub上提交了这个问题:https://github.com/Microsoft/visualfsharp/issues/338