【问题标题】:Converting a \u escaped Unicode string to ASCII将 \u 转义的 Unicode 字符串转换为 ASCII
【发布时间】:2013-07-19 16:04:44
【问题描述】:

看完iconv和Encoding的全部内容后,我还是一头雾水。

我正在抓取 web page 的源代码,我有一个如下所示的字符串:'pretty\u003D\u003Ebig'(在 R 控制台中显示为 'pretty\\\u003D\\\u003Ebig')。我想把它转换成ASCII字符串,应该是'pretty=>big'。

更简单地说,如果我设置

x <- 'pretty\\u003D\\u003Ebig'

如何对x 执行转换以生成pretty=&gt;big?

有什么建议吗?

【问题讨论】:

  • 复制此问题可能需要您使用的代码。

标签: r unicode text-processing iconv unicode-string


【解决方案1】:

我很同情;过去我一直在为 R 和 unicode 文本而苦苦挣扎,但并不总是成功。如果您的数据在 x 中,则首先尝试全局替换,如下所示:

x <- gsub("\u003D", "=>", x)

我有时会使用类似的结构

lapply(x, utf8ToInt)

查看高代码点的位置,例如任何超过 150 的内容。这有助于我定位由不间断空格引起的问题,例如,这些空格似乎不时弹出。

【讨论】:

  • 我需要使用x &lt;- gsub("\u003D\u003E", "=&gt;", x),但我不想涵盖所有可能的情况。请注意,lapply(x, utf8ToInt) 产生 112 114 101 116 116 121 92 48 48 51 68 92 117 48 48 51 69 98 105 103,因此它们都是低代码点!我只需要撤消 \u 转义!
  • 啊,好点子,我通常处理的亚洲脚本确实会产生高分,这显然有点不同。
【解决方案2】:
> iconv('pretty\u003D\u003Ebig', "UTF-8", "ASCII")
[1] "pretty=>big"

但你似乎有额外的逃避

【讨论】:

  • 没错!我忍不住额外的逃避:这就是web-page 返回的内容(单击它,查看源代码并向下滚动到数据)。
  • 比较cat('pretty\u003D\u003Ebig')和cat('pretty\\u003D\\u003Ebig')也很有启发意义。您在控制台输入的数据转义与您通过其他方式获得的数据转义之间存在很大差异。
  • 你在用windows吗?
【解决方案3】:

这里的诀窍是'\\u003D' 实际上是 6 个字符,而您想要的 '\u003D' 只有一个字符。另一个技巧是,要匹配那些反斜杠,您需要在模式中使用双重转义的反斜杠:

gsub("\\\\u003D\\\\u003E", "\u003D\u003E", x)
#[1] "pretty=>big"

要用一个字符替换多个字符,您需要定位整个模式。您不能简单地删除反斜杠。 (由于您已经指出这是一个更普遍的问题,我认为答案可能在于修改您尚未描述的下载此文本的方法。)

当我加载您的函数和依赖项时,此代码有效:

> freq <- ngram(c('pretty\u003D\u003Ebig'), year_start = 1950)
> 
> str(freq)
'data.frame':   59 obs. of  4 variables:
 $ Year     : num  1950 1951 1952 1953 1954 ...
 $ Phrase   : Factor w/ 1 level "pretty=>big": 1 1 1 1 1 1 1 1 1 1 ...
 $ Frequency: num  1.52e-10 6.03e-10 5.98e-10 8.27e-10 8.13e-10 ...
 $ Corpus   : Factor w/ 1 level "eng_2012": 1 1 1 1 1 1 1 1 1 1 ...

(所以我想我仍然不清楚用例。)

【讨论】:

  • 下载发生位置的血腥细节是here,但只需使用x &lt;- 'pretty\\u003D\\u003Ebig' 就可以重现问题。
  • 我需要确定多个缺失函数错误的来源,并在运行之前加载了 RCurl、stringr、httr 和 RJSONIO。我尝试使用您在这些函数上方的一些注释代码,但仍然不确定我是否有一个测试用例可以处理。
  • 产生错误的相关调用是ngram("pretty=&gt;big"),但对这个包的引用只是为了显示动机:对于一个可重复的例子来说太多了!
  • 我应该补充一点,接受@Hong Ooi 的解决方案后,我的包不再给出错误。以前,调用ngram("pretty=&gt;big") 会得到$ Phrase : Factor w/ 1 level "pretty\u003D\u003Ebig"。
  • 请注意,我仍然对没有eval 和parse 是否可以完成感兴趣。原来的例子是:假设我们给定了x &lt;- 'pretty\\u003D\\u003Ebig',需要将它转换为'pretty=&gt;big'。而不是ngramr 包,您可以将激励示例放在this page 的源代码中。查看页面搜索,搜索\u003D,就会发现问题!
【解决方案4】:

eval(parse)的用途!

eval(parse(text=paste0("'", x, "'")))

这当然有其自身的问题,例如必须手动转义字符串中的任何引号。但它应该适用于任何可能出现的有效 Unicode 序列。

【讨论】:

【解决方案5】:

虽然我接受了Hong ooi的回答,但我还是忍不住想parse和eval是一个重量级的解决方案。此外,正如所指出的那样,它并不安全,尽管对于我的应用程序,我可以确信我不会得到危险的报价。

因此,我设计了一种替代方法,有点残酷:

udecode <- function(string){
  uconv <- function(chars) intToUtf8(strtoi(chars, 16L))
  ufilter <- function(string) {
    if (substr(string, 1, 1)=="|") uconv(substr(string, 2, 5)) else string
  }
  string <- gsub("\\\\u([[:xdigit:]]{4})", ",|\\1,", string, perl=TRUE)
  strings <- unlist(strsplit(string, ","))
  string <- paste(sapply(strings, ufilter), collapse='')
  return(string)
}

欢迎任何简化!

【讨论】:

    【解决方案6】:

    使用解析,但不评估结果:

    x1 <- 'pretty\\u003D\\u003Ebig'
    x2 <- parse(text = paste0("'", x1, "'"))
    x3 <- x2[[1]]
    x3
    # [1] "pretty=>big"
    is.character(x3)
    # [1] TRUE
    length(x3)
    # [1] 1
    

    【讨论】:

    • as.character(x2) 也可以工作并将被矢量化(即:as.character(parse(text=paste0("'", rep(x1,3), "'"))))。 shQuote(x1) 也可以代替 paste0 方便。
    【解决方案7】:

    使用stringi 包:

    > x <- 'pretty\\u003D\\u003Ebig'
    > stringi::stri_unescape_unicode(x)
    [1] "pretty=>big"
    

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 2018-03-21
      • 2012-11-27
      • 2016-11-04
      • 2015-03-29
      • 2012-07-19
      相关资源
      最近更新 更多