将类似于<U+0161>的UTF8码点字符串转换为UTF8。

3

我有一个文本文件,其中包含一些Unicode字符的回退转换(以尖括号表示的Unicode代码点)。因此,它包含例如foo<U+017E>bar应该是"foošbar"。是否有一种简单的方法在R中将整个文件转换为UTF8,并将这些字符转换?不幸的是,我在Windows上并找不到受支持的UTF-8区域设置。


UTF8是一种编码,不是区域设置。无论如何,自2000年以来,Windows本地化使用Unicode。然而,R包混合使用Unicode和ANSI代码,然后依赖于更改本地化设置来处理编码问题。你实际上尝试了什么?不同的软件包有不同的怪癖。其中一些不幸地混淆了语言和编码。 - Panagiotis Kanavos
这个文件的编码和内容是什么?它是否使用Unicode编码之一?那么它可以包含foošbar而不会有任何转换问题。你确定问题不是RStudio或RRO的显示字体吗? - Panagiotis Kanavos
我的问题是我无法在Windows上切换到UTF-8友好的语言环境;像Sys.setlocale("LC_ALL", 'en_US.UTF-8')这样的东西不起作用,我不知道为什么。所以,无论文件采用哪种编码方式,我都会遇到这个问题。 - user43018
“本地化”与国家有关,而与Unicode编码无关。 Sys.setlocale实际上是一种R解决方案,允许使用ANSI编译的软件包处理Unicode数据-只要它们不尝试检查值。例如,我没有问题从文件中输入或加载“foošbar”。但某些软件包在处理加载的文本时会出现错误,而其他软件包则没有问题。甚至有一些混合使用Unicode和ANSI代码的情况。 - Panagiotis Kanavos
展示问题的代码是什么?替换字符串只是一种权宜之计。 - Panagiotis Kanavos
2个回答

5
也许:
library(stringi)
library(magrittr)

"foo<U+0161>bar and cra<U+017E>y" %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]+)>", "\\\\u$1") %>% 
  stri_unescape_unicode() %>% 
  stri_enc_toutf8()
## [1] "foošbar and cražy"

可能会起作用(在macOS上我不需要最后一次转换,但在Windows上您可能需要)。


不需要进行转换,Windows本身就支持Unicode。然而,R包经常混淆Unicode和ANSI代码。更糟糕的是,许多R包无法识别编码,而是尝试从系统的语言环境或区域设置中猜测。这使得在尝试读取多个Unicode编码甚至多个日期和数字格式时变得非常有趣。 - Panagiotis Kanavos

2

之前的答案适用于代码点恰好为四位数的情况。这里提供一种修改后的版本,适用于介于1到8位数之间的任何数字。

library(stringi)
library(magrittr)

"foo<U+0161>bar and cra<U+017E>y, Phoenician letter alf <U+10900>" %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{4})>", "\\\\u$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{5})>", "\\\\U000$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{6})>", "\\\\U00$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{7})>", "\\\\U0$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{8})>", "\\\\U$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{1})>", "\\\\u000$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{2})>", "\\\\u00$1") %>% 
  stri_replace_all_regex("<U\\+([[:alnum:]]{3})>", "\\\\u0$1") %>% 
  stri_unescape_unicode() %>% 
  stri_enc_toutf8()
## [1] "foošbar and cražy, Phoenician letter alf "

但是之前的答案不应该也适用于任意数量的数字吗?我的意思是[[:alnum:]]表示任何字母数字字符,加号表示一个或多个。 (当然,也许在你回答后进行了编辑...) - Benjamin
小写的转义码\u可以接受最多四个数字。例如,其他答案中提出的解决方案将无法正确处理"<U+102A0>",将其转换为\u102A0,即字符<U+102A>后跟一个字面上的零。此外,如果代码点未被特殊地填充为四位数字,则会出现问题:stri_unescape_unicode()要求\u后跟四个数字(\U后跟八个数字)。 - mvkorpel
1
该死,我明白你的意思了!正则表达式本身可以匹配所有内容,但是在这种情况下,它替换模式的结果无法使用。尽管 R 可以使用 "最多 8 个" 字符来使用 \U(如果我打印 "\U102A0",R 会输出 "\U000102a0"),但是 stri_unescape_unicode 非常严格:它只接受 \u1234\U12345678\U102A0 会抛出错误。我很高兴我问了,谢谢! - Benjamin
也就是说,我不能只用stri_replace_all_regex("<U\\+([[:alnum:]]{1,8})>", "\\\\U$1")来替换原始的解决方案。 - Benjamin

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