0

我有两个几乎等效的字符串。它们看起来一样。

str1<-"Diş Hekimliği Fakültesi"
str2<-"Diş Hekimliği Fakültesi"

但是当我尝试nchar()它们时,它们分别返回 26 和 23 个字符。当我使用strsplit();

strsplit(str1,split="")
[[1]]
 [1] "D" "i" "s" "̧"   " " "H" "e" "k" "i" "m" "l" "i" "g" "̆"   "i" " " "F" "a" "k" "u" "̈"   "l" "t" "e" "s" "i"

strsplit(str2,split="")
[[1]]
 [1] "D" "i" "ş" " " "H" "e" "k" "i" "m" "l" "i" "ğ" "i" " " "F" "a" "k" "ü" "l" "t" "e" "s" "i"

每个语言特定的特殊字符都算作两个字符。如何将str1变成str2?我唯一的手动解决方案是使用gsub().

附言。不幸的是,我不能把这个例子完整地带到这里。当您尝试复制粘贴代码时,它将都是 23 个字符。这里有复制粘贴的东西。

4

1 回答 1

0

iconv函数是一个系统特定的函数,用于管理国际编码之间的音译。有一个函数iconvlist可以返回您的操作系统工具使用的名称向量;我在我的系统上运行了所有 419 个这样的编码,sapplytry查看是否可以将 str1(23 个字符)转换为 26,反之亦然,并在我的机器上找到了两个这样的编码。由于我使用的是 Mac,因此我无法保证这些特定值对您有用,因为您不会透露您的操作系统状态:

我能够将 MWE 与您上面的strsplit-result的输出放在一起str2

str1<-"Diş Hekimliği Fakültesi"
str3 <- scan(what="")
 "D" "i" "s" "̧"   " " "H" "e" "k" "i" "m" "l" "i" "g" "̆"   "i" " " "F" "a" "k" "u" "̈"   "l" "t" "e" "s" "i"
#27: 
#Read 26 items
> str3c <- paste0(str3, collapse="")
> nchar(str3c)
[1] 26
> str1
[1] "Diş Hekimliği Fakültesi"

在出现许多错误消息(由于封闭而不会停止执行之后try(),我得到了使用此代码的 2 个编码的列表:

?iconv
which(sapply( try(utils::head(iconvlist(), n = 419)), function(xc) 
                                                  try(nchar(iconv(str1, to=xc))))==26)
#--------snipped large number of error messages-------
Error in nchar(iconv(str1, to = xc)) : invalid multibyte string 1
UTF-8-MAC  UTF8-MAC 
      400       402 

然后认为反过来可能会成功(因为 str1 以 23-char 对象开始)我成功地尝试了:

> iconv(str3c,from="UTF-8-MAC", to="UTF-8")
[1] "Diş Hekimliği Fakültesi"
> nchar(iconv(str3c,from="UTF-8-MAC", to="UTF-8"))
[1] 23

查看Windows iconv 的网页可以看到有一个 {10081, "x-mac-turkish"}, /* Turkish (Mac) */. 如果您在 Windoze 上,也许可以尝试一下。

=================

下面的早期调查(我认为知道如何分离字符值很有用。)

好的。实际上,我可以将 MWE 与上面的内容放在一起:

str1<-"Diş Hekimliği Fakültesi"
str3 <- scan(what="")
#1: "D" "i" "s" "̧"   " " "H" "e" "k" "i" "m" "l" "i" "g" "̆"   "i" " " "F" "a" "k" "u" "̈"   "l" "t" "e" "s" "i"
#27: 
#Read 26 items
> str3c <- paste0(str3, collapse="")
> nchar(str3c)
[1] 26
> str1
[1] "Diş Hekimliği Fakültesi"

现在做一些字符黑客:

> ?charToRaw
> charToRaw(str3c)
 [1] 44 69 73 cc a7 20 48 65 6b 69 6d 6c 69 67 cc 86 69 20 46 61 6b 75 cc 88 6c 74 65
[28] 73 69
> charToRaw(str1)
 [1] 44 69 c5 9f 20 48 65 6b 69 6d 6c 69 c4 9f 69 20 46 61 6b c3 bc 6c 74 65 73 69

因此,请查看代表您的第三个字母的三个 Raw 项目。似乎第二个表示使用了一个基本字符,它用十六进制“cc”将其退格,然后打印降序。现在看看我们是否可以用正则表达式识别它们:

 rawToChar( charToRaw(str3c) [3])
#[1] "s"
 rawToChar( charToRaw(str3c) [4])
#[1] "\xcc"
 rawToChar( charToRaw(str3c) [5])
#[1] "\xa7"
 grep("s\\xcc\\xa7", str3c)
#[1] 1   # Success!

如果您使用这些单词的拆分版本,我认为这是一个 gsub 可能比您最终得到的更有效:

gsub("s\\xcc\\xa7", "\\c5\\9f", str3c)
#[1] "Diş Hekimliği Fakültesi"

另请注意,在一个 R 中实际上有 29 个原始条目告诉您有 26 个“字符”(而在应该有 23 个的那个中有 26 个)。我认为这三个cc(退格)实际上并没有被计算在内。

于 2015-04-04T18:49:05.190 回答