代理对检测失败
Surrogate Pair Detection Fails
我正在使用 F# 进行一个次要项目,该项目涉及将现有的 C# 代码移植到 F#,我似乎发现两种语言处理正则表达式的方式存在差异(我将其发布到希望发现我只是做错了什么)。
这个次要函数使用概述的正则表达式技巧简单地检测代理对 here。这是当前的实现:
let isSurrogatePair input =
Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
如果我然后像这样针对已知的代理对执行它:
let result = isSurrogatePair "野"
printfn "%b" result
我在 FSI window 中得到 false
。
如果我使用等效的 C#:
public bool IsSurrogatePair(string input)
{
return Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]");
}
和相同的输入值,我(正确地)得到 true
回来。
这是一个真实的问题吗?我只是在我的 F# 实现中做错了什么吗?
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
幸运的是,此解决方法有效:
> let s = new System.String( [| char 0xD800 |] )
s.[0] |> uint16
;;
val s : System.String = "�"
val it : uint16 = 55296us
基于该发现,我可以构建 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)
此版本正确returns true
供您输入。
我刚刚在 GitHub 上提交了这个问题:https://github.com/Microsoft/visualfsharp/issues/338
似乎这是一个合法的 F# 错误,没有争论。只是想提出一些替代解决方法。
不要在字符串本身中嵌入问题字符,使用正则表达式的正常 unicode 支持指定它们。匹配 unicode 代码点 XXXX
的正则表达式模式是 \uXXXX
,因此只需转义反斜杠或使用逐字字符串:
Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
// or
Regex.IsMatch(input, @"[\uD800-\uDBFF][\uDC00-\uDFFF]")
对 unicode 块使用内置正则表达式支持:
// high surrogate followed by low surrogate
Regex.IsMatch(input, @"(\p{IsHighSurrogates}|\p{IsHighPrivateUseSurrogates})\p{IsLowSurrogates}")
或属性
// 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# 进行一个次要项目,该项目涉及将现有的 C# 代码移植到 F#,我似乎发现两种语言处理正则表达式的方式存在差异(我将其发布到希望发现我只是做错了什么)。
这个次要函数使用概述的正则表达式技巧简单地检测代理对 here。这是当前的实现:
let isSurrogatePair input =
Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
如果我然后像这样针对已知的代理对执行它:
let result = isSurrogatePair "野"
printfn "%b" result
我在 FSI window 中得到 false
。
如果我使用等效的 C#:
public bool IsSurrogatePair(string input)
{
return Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]");
}
和相同的输入值,我(正确地)得到 true
回来。
这是一个真实的问题吗?我只是在我的 F# 实现中做错了什么吗?
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
幸运的是,此解决方法有效:
> let s = new System.String( [| char 0xD800 |] )
s.[0] |> uint16
;;
val s : System.String = "�"
val it : uint16 = 55296us
基于该发现,我可以构建 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)
此版本正确returns true
供您输入。
我刚刚在 GitHub 上提交了这个问题:https://github.com/Microsoft/visualfsharp/issues/338
似乎这是一个合法的 F# 错误,没有争论。只是想提出一些替代解决方法。
不要在字符串本身中嵌入问题字符,使用正则表达式的正常 unicode 支持指定它们。匹配 unicode 代码点 XXXX
的正则表达式模式是 \uXXXX
,因此只需转义反斜杠或使用逐字字符串:
Regex.IsMatch(input, "[\uD800-\uDBFF][\uDC00-\uDFFF]")
// or
Regex.IsMatch(input, @"[\uD800-\uDBFF][\uDC00-\uDFFF]")
对 unicode 块使用内置正则表达式支持:
// high surrogate followed by low surrogate
Regex.IsMatch(input, @"(\p{IsHighSurrogates}|\p{IsHighPrivateUseSurrogates})\p{IsLowSurrogates}")
或属性
// 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}")