OCaml:如何解码unicode转义字符串?

4

给定以下字符串:

let str = "#include \\u003Cunordered_map\\u003E\\u000D\\u000A"

如何在OCaml中将unicode-escape字符串解码为Unicode字符串或在我的情况下是Ascii字符串?

在Python中,我可以很容易地执行以下操作:

str.decode("unicode-escape")
1个回答

3
如果你的嵌入式转义序列总是编码ASCII字符,正如你所说,你可以找到它们并替换为解码后的等价物:
let decode s =
    let re = Str.regexp "\\\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]" in
    let s1 n = String.make 1 (Char.chr n) in
    let subst = function
    | Str.Delim u -> s1 (int_of_string ("0x" ^ String.sub u 2 4))
    | Str.Text t -> t
    in
    String.concat "" (List.map subst (Str.full_split re s))

这个对你的例子有效:
val decode : string -> string = <fun>
# decode "#include \\u003Cunordered_map\\u003E\\u000D\\u000A";;
- : string = "#include <unordered_map>\r\n"

实际上,Python内置了解码这些序列的支持。

更新

为了支持所有四位十六进制转义序列"\uXXXX",通过转换为UTF-8,您可以使用以下代码:

let utf8encode s =
    let prefs = [| 0x0; 0xc0; 0xe0 |] in
    let s1 n = String.make 1 (Char.chr n) in
    let rec ienc k sofar resid =
        let bct = if k = 0 then 7 else 6 - k in
        if resid < 1 lsl bct then
            (s1 (prefs.(k) + resid)) ^ sofar
        else
            ienc (k + 1) (s1 (0x80 + resid mod 64) ^ sofar) (resid / 64)
    in
    ienc 0 "" (int_of_string ("0x" ^ s))

let decode2 s =
    let re = Str.regexp "\\\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]" in
    let subst = function
    | Str.Delim u -> utf8encode (String.sub u 2 4)
    | Str.Text t -> t
    in
    String.concat "" (List.map subst (Str.full_split re s))

它也适用于您的示例和其他一些示例:
val utf8encode : string -> string = <fun>
val decode2 : string -> string = <fun>
# decode2 "#include \\u003Cunordered_map\\u003E\\u000D\\u000A";;
- : string = "#include <unordered_map>\r\n"
# print_endline (decode2 "\\u00A2");;
¢
- : unit = ()
# print_endline (decode2 "\\u20AC");;
€
- : unit = ()

谢谢。这适用于ASCII编码的转义序列。如果我有utf-8编码的转义序列怎么办?OCaml是否有易于使用的库来处理它?在Python中,我可以轻松地执行以下操作:str = str.encode(“utf-8”)。decode(“unicode-escape”) - Oliver Young
Batteries中有一些UTF-8支持。说实话,除非我已经使用的某个库支持UTF-8,否则我可能会编写自己的转换代码。这是一个简单的转换,我将添加代码。 - Jeffrey Scofield
感谢详细的回答!非常有用。 - Oliver Young
只是确认一下,uft8encode 只能编码最多 3 字节的 utf8,不能编码 4 字节的 utf8,对吗? - Oliver Young
对于第五个字节,只需添加“next”前缀(0xf8)。对于六个字节,还需添加0xfc。 - Jeffrey Scofield
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接