取消转义字符串中的 unicode

Posted

技术标签:

【中文标题】取消转义字符串中的 unicode【英文标题】:Unescape unicode in character string 【发布时间】: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"

【问题讨论】:

我在这里遇到了类似的问题:***.com/questions/20067206/… 不确定是否有任何简单的解决方案。 这是一个不同的问题。您正在尝试解析无效的 JSON。 【参考方案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

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

【讨论】:

以上是关于取消转义字符串中的 unicode的主要内容,如果未能解决你的问题,请参考以下文章

Python 2.7:如何将字符串中的 unicode 转义转换为实际的 utf-8 字符

如何使用 Gradle 自动转义 Java 属性文件中的 unicode 字符?

六位 unicode 转义值比较

如何取消转义html字符串中的引号

Python unicode转义字符u的处理

BigQuery:如何取消转义额外转义/序列化的 JSON 字符串