【问题标题】:Unescape unicode in character string取消转义字符串中的 unicode
【发布时间】:2014-09-17 02:21:35
【问题描述】:

RJSONIO 中有一个长期存在的bug 用于解析包含 unicode 转义序列的 json 字符串。似乎需要在 libjson 中修复该错误,这可能不会很快发生,所以我正在寻找在 R 中创建一个解决方法,在将它们提供给 json 解析器之前取消转义 \uxxxx 序列。

一些上下文:json数据总是unicode,默认使用utf-8,所以一般不需要转义。但由于历史原因,json 确实支持转义的 unicode。因此json数据

{"x" : "Zürich"}

{"x" : "Z\u00FCrich"}

是等效的,并且在解析时应该产生完全相同的输出。但无论出于何种原因,后者在RJSONIO 中不起作用。额外的confusion 是由于 R 本身也支持转义的 unicode 造成的。因此,当我们在 R 控制台中键入 "Z\u00FCrich" 时,它会自动正确地转换为 "Zürich"。为了得到实际的 json 字符串,我们需要转义反斜杠本身,它是 json 中 unicode 转义序列的第一个字符:

test <- '{"x" : "Z\\u00FCrich"}'
cat(test)

所以我的问题是:给定 R 中的一个大 json 字符串,我怎样才能对所有转义的 unicode 序列进行转义? IE。如何用相应的 unicode 字符替换所有出现的\uxxxx?同样,这里的\uxxxx 代表一个实际的 6 个字符的字符串,以反斜杠开头。所以unescape 函数应该满足:

#Escaped string
escaped <- "Z\\u00FCrich"

#Unescape unicode
unescape(escaped) == "Zürich"

#This is the same thing
unescape(escaped) == "Z\u00FCrich"

可能使事情复杂化的一件事是,如果反斜杠本身在 json 中用另一个反斜杠转义,则它 不是 unicode 转义序列的一部分。例如。 unescape 也应该满足:

#Watch out for escaped backslashes
unescape("Z\\\\u00FCrich") == "Z\\\\u00FCrich"
unescape("Z\\\\\\u00FCrich") == "Z\\\\ürich"

【问题讨论】:

标签: regex json r unicode utf-8


【解决方案1】:

stringi 包中有这个功能:)

require(stringi)    
escaped <- "Z\\u00FCrich"
escaped
## [1] "Z\\u00FCrich"
stri_unescape_unicode(escaped)
## [1] "Zürich"

【讨论】:

  • 这在后面的测试中失败了,因为它也取消了换行符、制表符、反斜杠等。但是json 需要那些保持转义。我想取消转义 \u 序列,没有别的。
【解决方案2】:

可能是这样的?

\"x\"\s:\s\"([^"]*?)\"

这不是寻找字母。只等报价

【讨论】:

    【解决方案3】:

    在玩了更多之后,我认为我能做的最好的事情是使用正则表达式搜索\uxxxx 模式,然后使用 R 解析器解析它们:

    unescape_unicode <- function(x){
      #single string only
      stopifnot(is.character(x) && length(x) == 1)
    
      #find matches
      m <- gregexpr("(\\\\)+u[0-9a-z]{4}", x, ignore.case = TRUE)
    
      if(m[[1]][1] > -1){
        #parse matches
        p <- vapply(regmatches(x, m)[[1]], function(txt){
          gsub("\\", "\\\\", parse(text=paste0('"', txt, '"'))[[1]], fixed = TRUE, useBytes = TRUE)
        }, character(1), USE.NAMES = FALSE)
    
        #substitute parsed into original
        regmatches(x, m) <- list(p)
      }
    
      x
    }
    

    这似乎适用于所有情况,我还没有发现任何奇怪的副作用

    【讨论】:

      猜你喜欢
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 2015-05-31
      • 1970-01-01
      相关资源
      最近更新 更多