R中的unicode字符转换

时间:2014-05-22 12:40:51

标签: r unicode

我有这个MTST列,打印后会产生

 [1] "<U+0391>G<U+03A1><U+0399><U+039D><U+0399><U+039F>                                 "
 [2] "<U+0391>G<U+03A7><U+0399><U+0391><U+039B><U+039F>S                                "
 [3] "<U+0391><U+0399>G<U+0399><U+039D><U+0391>                                  "
 [4] "<U+0391><U+0399>G<U+0399><U+039F>                                   "
 [5] "<U+0391><U+0399><U+0394><U+0397><U+03A8><U+039F>S                                 "
 [6] "<U+0391><U+039A><U+03A4><U+0399><U+039F>(<U+03A0><U+03A1><U+0395><U+0392><U+0395><U+0396><U+0391>)                          "
 [7] "<U+0391><U+039B><U+0395><U+039E><U+0391><U+039D><U+0394><U+03A1><U+039F><U+03A5><U+03A0><U+039F><U+039B><U+0397>                          "
 [8] "<U+0391><U+039B><U+0399><U+0391><U+03A1><U+03A4><U+039F>S                                "

我尝试使用Unicode库并执行MTST<- as.u_char(MTST)提供

[1] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>

我也尝试了dumpdput但没有改变。

请注意,MTST最初的类型为character

感谢您的帮助。感谢

显示<{1}}下面的

编辑

dput(MTST)

3 个答案:

答案 0 :(得分:6)

你所拥有的内容看起来像普通的7位ASCII字符,并试图通过包装其中的一些来编码Unicode代码点:<U+abcd>

据我所知,这不是Unicode的公认编码,部分原因是你如何在文本中加入真正的<?我想每个<可以是<U+jklm>,其中jklm是一个尖括号的代码......但是ick。

所以,首先,尝试从生成此ascii编码的混乱中获取UTF-8编码的字符串!

然而......经过一些严肃的头发拉动......

stringi救援!在哪里&#39; MTST&#39;是你的东西,首先将尖括号表示法转换为反斜杠-u然后使用stri_unescape_unicode

> require(stringi)
> greek2=gsub(">","", gsub("<U\\+","\\\\u",MTST))
> stri_unescape_unicode(greek2)
[1] "ΑGΡΙΝΙΟ                                 "
[2] "ΑGΧΙΑΛΟS                                "
[3] "ΑΙGΙΝΑ                                  "
[4] "ΑΙGΙΟ                                   "
[5] "ΑΙΔΗΨΟS                                 "
[6] "ΑΚΤΙΟ(ΠΡΕΒΕΖΑ)                          "

一直到

[123] "FΥΧΤΙΑ                                  "
[124] "ΧΑΛΚΙΔΑ                                 "
[125] "ΧΑΝΙΑ                                   "
[126] "ΧΙΟS                                    "
[127] "ΧΡΥSΟΥΠΟΛΗ_ΚΑΒΑΛΑ                       "
[128] "OΡΕΟΙ                                   "

一旦我在你的&#34; dput&#34;中修复了奇怪的逗号和引号。数据(为您编辑问题)。

答案 1 :(得分:2)

我已经在基地R中编写了一个方便,通用且内部稍微不稳定的功能,可以很好地实现此目的。这是:

dsub <- function(input,re,f=function(s,d) paste0(s,c(if (length(d)==0L) NULL else paste0('<',d,'>'),''),collapse='')) {
    splits <- strsplit(input,re,perl=T);
    delims <- lapply(strsplit(gsub(paste0('(',re,')'),'.\\1',input,perl=T),paste0('\\.(?=',re,')'),perl=T),function(x) sub(paste0('^(',re,').*'),'\\1',x[-1],perl=T))
    lapply(1:length(splits), function(i) { s <- splits[[i]]; d <- delims[[i]]; f(c(s,if (length(s)==length(d)) '' else NULL),d); } );
};

该函数背后的想法是提供更强大的strsplit()变体,它允许您不仅将输入字符串拆分为字段,而且为每个输入字符串设置一个lambda,该字符串同时接收两个字段列表(我在代码中称之为splitss)以及分隔每个字段的分隔符(称为delimsd)。

重要的是,最终字段永远不会分隔,因此s总是比d长一个元素。现在,应该注意的是strsplit()通常不是这样的;如果输入字符串中的最后一个分隔符包含所述字符串的结尾,它实际上并没有返回一个最后的空字符串字段,但是我已经修补了#34;#34;修补了&#34;为了保持一致性,我在dsub()函数中的行为;对于lambda f()的每次调用,保证sd长一个元素。

第二个怪癖与我提取分隔符的方式有关;说起来容易做起来难。我再次使用strsplit(),但是使正则表达式成为零宽度前瞻断言以保留分隔符内容,然后,在分割之后,我调用sub()来去除分隔符后的所有内容。现在,当您使用匹配多个字符的完全零宽度正则表达式时,strsplit()表现得很奇怪;我认为发生的事情是它在同一点上匹配正则表达式两次,然后在相邻的返回字段中拆分第一个和后续字符。为了解决这个问题,我在分隔符的每个实例之前添加了一个虚拟char,然后将该char(非零宽度,就在前瞻断言之前)作为分割正则表达式的一部分进行匹配,这自然会将其剥离。

无论如何,这是一个简单的演示,展示如何使用dsub()与lambda调用intToUtf8()来进行这种&#34; Unicode插值&#34;:

input <- c('Luc TR<U+00c9>HAN','aa<U+00ca>bb<U+00cb>cc','<U+00CC><U+00Cd>','','  ');
re <- '<U\\+([0-9a-fA-F]{4})>';
f <- function(s,d) paste0(s,c(if (length(d)==0L) NULL else intToUtf8(paste0('0x',sub(re,'\\1',d)),multiple=T),''),collapse='');
do.call(c,dsub(input,re,f));
## [1] "Luc TRÉHAN" "aaÊbbËcc"   "ÌÍ"         ""           "  "

使用此问题中给出的相当广泛的示例数据:

input <- c("<U+0391>G<U+03A1><U+0399><..."); ## (excerpted)
do.call(c,dsub(input,re,f));
##   [1] "ΑGΡΙΝΙΟ                                 " "ΑGΧΙΑΛΟS                                " "ΑΙGΙΝΑ                                  " "ΑΙGΙΟ                                   "
##   [5] "ΑΙΔΗΨΟS                                 " "ΑΚΤΙΟ(ΠΡΕΒΕΖΑ)                          " "ΑΛΕΞΑΝΔΡΟΥΠΟΛΗ                          " "ΑΛΙΑΡΤΟS                                "
##   [9] "ΑΝΑΒΡΥΤΑ                                " "ΑΝΔΡΑΒΙΔΑ                               " "ΑΝOGΕΙΑ                                 " "ΑΡΑΞΟS                                  "
##  [13] "ΑΡΑΧOΒΑ                                 " "ΑΡGΟS(ΠΥΡGΕΛΑ)                          " "ΑΡGΟSΤΟΛΙ                               " "ΑΡΤΑ (ΠΟΛΗ)                             "
##  [17] "ΑΡΤΑ (FΙΛΟTΕΗ)                          " "ΑSΤΕΡΟSΚΟΠΕΙΟ                           " "ΑSΤΡΟS                                  " "ΑSΤΥΠΑΛΑΙΑ                              "
##  [21] "ΒΑΜΟS                                   " "ΒΕΛΟ (ΚΟΡΙΝTΙΑS)                        " "ΒΟΛΟS                                   " "ΒΥΤΙΝΑ                                  "
##  [25] "GΟΡΤΥS                                  " "GΥTΕΙΟ                                  " "ΔΕSFΙΝΑ                                 " "ΔΙΑΒΟΛΙΤSΙ                              "
##  [29] "ΔΟΜΟΚΟS                                 " "ΔΡΑΜΑ                                   " "ΕΔΕSSΑ                                  " "ΕΛΕΥSΙΝΑ                                "
##  [33] "ΕΛΛΗΝΙΚΟ aeρ                            " "ΖΑΚΥΝTΟS                                " "ΖΑΚΥΝTΟS_ΠΟΛΗ                           " "ΖΑΡΟS                                   "
##  [37] "ΗΡΑΚΛΕΙΟ                                " "TΑSΟS                                   " "TΗΡΑ (SΑΝΤΟΡΙΝΗ"                          "ΙΕΡΑΠΕΤΡΑ                               "
##  [41] "ΙΚΑΡΙΑ_Α/Δ                              " "ΙOΑΝΝΙΝΑ                                " "ΚΑΒΑΛΑ (ΠΟΛΗ)                           " "ΚΑΒΑΛΑ(ΑΜΥGΔΑΛΕOΝΑS)                    "
##  [45] "ΚΑΛΑΒΡΥΤΑ                               " "ΚΑΛΑΜΑΤΑ                                " "ΚΑΛΑΜΠΑΚΑ                               " "ΚΑΡΔΙΤSΑ                                "
##  [49] "ΚΑΡΠΑTΟS_Α/Δ                            " "ΚΑΡΠΑTΟS_ΠΟΛΗ                           " "ΚΑΡΠΕΝΗSΙ                               " "ΚΑΡΥSΤΟS                                "
##  [53] "ΚΑSΟS                                   " "ΚΑSΤΕΛΛΙ                                " "ΚΑSΤΟΡΙΑ                                " "ΚΕΡΚΥΡΑ                                 "
##  [57] "ΚΟΖΑΝΗ                                  " "ΚΟΜΟΤΗΝΗ                                " "ΚΟΝΙΤSΑ                                 " "ΚΟΡΙΝTΟS                                "
##  [61] "ΚΥTΗΡΑ_Α/Δ                              " "ΚΥΜΗ                                    " "ΚOS                                     " "ΚOS_ΠΟΛΗ                                "
##  [65] "ΛΑΜΙΑ                                   " "ΛΑΡΙSΑ                                  " "ΛΕΡΟS                                   " "ΛΕΥΚΑΔΑ (ΝΗSΙ)                          "
##  [69] "ΛΕOΝΙΔΙΟ                                " "ΛΗΜΝΟS                                  " "ΛΙΔOΡΙΚΙ                                " "ΜΑΚΕΔΟΝΙΑ                               "
##  [73] "ΜΑΡΑTOΝΑS                               " "ΜΕTOΝΗ                                  " "ΜΕSΟΛΟGGΙ                               " "ΜΗΛΟS_ΑΜS                               "
##  [77] "ΜΥΚΟΝΟS                                 " "ΜΥΤΙΛΗΝΗ                                " "ΝΑΞΟS                                   " "ΝΑΥΠΑΚΤΟS                               "
##  [81] "ΝΑΥΠΛΙΟ                                 " "ΝΕΑ FΙΛΑΔΕΛFΕΙΑ                         " "ΞΑΝTΗ                                   " "ΟΡΕSΤΙΑΔΑ                               "
##  [85] "ΠΑΙΑΝΙΑ                                 " "ΠΑΛΑΙΟΧOΡΑ                              " "ΠΑΡΟS_Α/Δ                               " "ΠΑΤΡΑ                                   "
##  [89] "ΠΕΙΡΑΙΑS                                " "ΠΟΛΥGΥΡΟS                               " "ΠΟΤΙΔΑΙΑ                                " "ΠΤΟΛΕΜΑΙΔΑ                              "
##  [93] "ΠΥΡGΟS                                  " "ΡΑFΗΝΑ                                  " "ΡΕTΥΜΝΟ                                 " "ΡΟΔΟS                                   "
##  [97] "SΑΜΟS                                   " "SΕΔΕS                                   " "SΕΡΡΕS                                  " "SΗΤΕΙΑ                                  "
## [101] "SΚΙΑTΟS                                 " "SΚΟΤΙΝΑ                                 " "SΚΥΡΟS                                  " "SΟΥΔΑ                                   "
## [105] "SΟΥFΛΙ                                  " "SΠΑΡΤΗ                                  " "SΠΑΤΑ(ΒΕΝΙΖΕΛΟS)                        " "SΠΕΤSΕS                                 "
## [109] "SΤΕFΑΝΙ (ΚΟΡΙΝTΙΑS)                     " "SΥΚΥOΝΑ                                 " "SΥΡΟS_Α/Δ                               " "ΤΑΝΑGΡΑ                                 "
## [113] "ΤΑΤΟΙ (ΔΕΚΕΛΕΙΑ)                        " "ΤΖΕΡΜΙΑΔΕS                              " "ΤΡΙΚΑΛΑ ΗΜΑTΕΙΑS                        " "ΤΡΙΚΑΛΑ TΕSSΑΛΙΑS                       "
## [117] "ΤΡΙΠΟΛΗ                                 " "ΤΥΜΠΑΚΙ                                 " "ΤΥΡΙΝTΑ                                 " "FΑΡSΑΛΑ                                 "
## [121] "FΛOΡΙΝΑ                                 " "FΟΥΡΝΗ                                  " "FΥΧΤΙΑ                                  " "ΧΑΛΚΙΔΑ                                 "
## [125] "ΧΑΝΙΑ                                   " "ΧΙΟS                                    " "ΧΡΥSΟΥΠΟΛΗ_ΚΑΒΑΛΑ                       " "OΡΕΟΙ                                   "

答案 2 :(得分:1)

这是恢复字符串中编码的真正解码字符的另一种方法(借用this question)。在这里,我们仔细匹配表单<U+[hex]>并将该十六进制值展开为一个正确大小的unicode字符,并进行一些位操作。

trueunicode <- function(x) {
    packuni<-Vectorize(function(cp) {
        bv <- intToBits(cp)
        maxbit <- tail(which(bv!=as.raw(0)),1)
        if(maxbit < 8) {
            rawToChar(as.raw(codepoint))
        } else if (maxbit < 12) {
            rawToChar(rev(packBits(c(bv[1:6], as.raw(c(0,1)), bv[7:11], as.raw(c(0,1,1))), "raw")))
        } else if (maxbit < 17){
            rawToChar(rev(packBits(c(bv[1:6], as.raw(c(0,1)), bv[7:12], as.raw(c(0,1)), bv[13:16], as.raw(c(0,1,1,1))), "raw")))    
        } else {
           stop("too many bits")
        }
    })
    m <- gregexpr("<U\\+[0-9a-fA-F]{4}>", x)
    codes <- regmatches(x,m)
    chars <- lapply(codes, function(x) {
        codepoints <- strtoi(paste0("0x", substring(x,4,7)))
        packuni(codepoints)

    })
    regmatches(x,m) <- chars
    Encoding(x)<-"UTF-8"
    x
}

使用样本

input <- c("<U+0391>G<U+03A1><U+0399><U+039D><U+0399><U+039F>", "<U+0391>G<U+03A7><U+0399><U+0391><U+039B><U+039F>S","<U+0391><U+0399>G<U+0399><U+039D><U+0391>", "<U+0391><U+0399>G<U+0399><U+039F>", "<U+0391><U+0399><U+0394><U+0397><U+03A8><U+039F>S","<U+0391><U+039A><U+03A4><U+0399><U+039F>(<U+03A0><U+03A1><U+0395><U+0392><U+0395><U+0396><U+0391>)")

你得到了

trueunicode(input)
# [1] "ΑGΡΙΝΙΟ"        "ΑGΧΙΑΛΟS"       "ΑΙGΙΝΑ"         "ΑΙGΙΟ"         
# [5] "ΑΙΔΗΨΟS"        "ΑΚΤΙΟ(ΠΡΕΒΕΖΑ)"