在 R 中同时使用正则表达式替换所有变音符号

14

我有一些德语文本,希望将其中所有的umlauts(ä,Ä,ü,Ü,ö,Ö)替换为ae,oe,ue等。

我可以分别进行替换(通过将每个替换保存到一个新文件中):

gsub(pattern = '[ä]', replacement = "ae",text)
gsub(pattern = '[ü]', replacement = "ue",text)
gsub(pattern = '[ö]', replacement = "oe",text)

但我能否用一个命令完成它(包括将大写字母替换为Ae、Oe和Ue等)?

我能用正则表达式吗?


你可能不能在一行中完成实际的工作,但是你可以定义一个函数来完成这个任务... - user824425
@Rhymoid 举个例子来说? - Daniel Yefimov
2
如果您传递一个命名向量,其中名称是模式,元素是替换项,例如 stringr::str_replace_all('üïëäö', c('ü' = 'ue', 'ï' = 'ie', 'ë' = 'ee', 'ä' = 'ae','ö' = 'oe'))(如果您喜欢,可以添加大写字母),则可以使用 stringr::str_replace_all 一次性替换它们所有。不过,您可能需要深入了解 stringi;您可以使用 stringi::stri_trans_general('üïëäö', 'latin-ascii') 删除重音符号,但它不会插入“e”字符。 - alistaire
你使用的字符集是哪个? - user824425
3个回答

11

你可以尝试一下

# install.packages("stringi) # uncomment & run if needed
str <- c("äöü", "ÄÖÜ")
stringi::stri_replace_all_fixed(
  str, 
  c("ä", "ö", "ü", "Ä", "Ö", "Ü"), 
  c("ae", "oe", "ue", "Ae", "Oe", "Ue"), 
  vectorize_all = FALSE
)
# [1] "aeoeue" "AeOeUe"

8

这里提供的一些解决方案可能会因为运行R的操作系统区域设定和输入字符串的编码不同而有效或无效。我在不同的操作系统和语言环境下遇到了这个问题很多次。目前我正在使用德语Windows 10开发R,但有时会在英语Ubuntu虚拟机上运行代码。

在Windows和Ubuntu上,包括de_DE和en_US,一个非常快速可靠的解决方案是:

https://github.com/gagolews/stringi/issues/269#issuecomment-488623874
> stringi::stri_trans_general("ä ö ü ß", "de-ASCII; Latin-ASCII")
[1] "ae oe ue ss"

在 ICU 转换 ID 中的分号 (;) 使其成为“复合 ID”。有关更多信息,请参见 ?stri_trans_general

2

有几种方法。其中两种已经根据stringistringr包进行了建议。

另一种解决方案使用gsubfn包。

text <- "ae = ä und oe = ö, UE = Ü. I also want Ä to be AE and not Ae"

# Solution depends on extra package "gsubfn"
require(gsubfn)
gsubfn(".", list("ä"="ae", "ö"="oe", "ü"="ue", "Ä" = "AE", "Ö" = "OE", "Ü" = "UE"), text)

当然,我们也可以自己编写函数,因为你可能不想为了一个单一的函数加载一个包(我个人尽量避免这种情况)。
# Solution 1
replace_umlauts <- function(x) {
  umlauts <- "äöü"
  UMLAUTS <- "ÄÖÜ"
  x <- gsub(pattern = paste0("([", UMLAUTS, "])"), replacement = "\\1E", x)
  x <- gsub(pattern = paste0("([", umlauts, "])"), replacement = "\\1e", x)
  x <- chartr(old = paste0(UMLAUTS, umlauts), new = "AOUaou", x)
  return(x)
}
replace_umlauts(text)

有趣的部分是基准测试。
require(microbenchmark)
require(stringi)
require(stringr)
require(gsubfn)
microbenchmark(
  myown = replace_umlauts(text),
  stringi = stringi::stri_replace_all_fixed(text, c("ä", "ö", "ü", "Ä", "Ö", "Ü"), c("ae", "oe", "ue", "AE", "OE", "UE"), vectorize_all = FALSE),
  stringr = stringr::str_replace_all(text, c("ü" = "ue", "ä" = "ae", "ö" = "oe", "Ä" = "AE", "Ö" = "OE", "Ü" = "UE")), 
  gsubfn = gsubfn(".", list("ä"="ae", "ö"="oe", "ü"="ue", "Ä" = "AE", "Ö" = "OE", "Ü" = "UE"), text),
  times = 500L
)

结果如下:
Unit: microseconds
    expr   min      lq      mean  median     uq    max neval
   myown  18.1   23.50   28.8510   30.45   32.6   63.3   500
 stringi  10.5   14.10   17.3808   17.80   19.8   46.3   500
 stringr 332.3  353.40  375.5458  371.85  387.5  586.1   500
  gsubfn 996.5 1042.55 1104.7458 1057.45 1075.2 7547.5   500

最快的解决方案是stringi::stri_replace_all_fixed。它比第二好的解决方案快近一倍,比stringr快10倍。在速度方面唯一可以接受的替代方案是自制的replace_umlauts函数。


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