R正则表达式:使用\\b与'Å'和'A'字符的区别

3

\\b代表单词边界。我不明白为什么这个运算符根据后面的字符有不同的效果。例如:

test1 <- 'aland islands'
test2 <- 'åland islands'

regex1 <- "[å|a]land islands"
regex2 <- "\\b[å|a]land islands"

grepl(regex1, test1, perl = TRUE)
[1] TRUE
grepl(regex2, test1, perl = TRUE)
[1] TRUE

grepl(regex1, test2, perl = TRUE)
[1] TRUE
grepl(regex2, test2, perl = TRUE)
[1] FALSE

只有在 perl = TRUE 的情况下才会出现这个问题:

grepl(regex1, test2, perl = FALSE)
[1] TRUE
grepl(regex2, test2, perl = FALSE)
[1] TRUE

很不幸,我的应用程序中绝对需要保留perl=TRUE


我无法确认:grepl("\\b[å|a]land islands", "åland islands", perl = TRUE) 对我来说返回 TRUE - Maurits Evers
@MauritsEvers 你在使用Windows吗? - wp78de
@wp78de 我使用的是MacOS和Linux操作系统。 - Maurits Evers
我无法复制这个错误。我在使用Windows系统。 - Onyambu
正如@wp78de在他们的回答中指出的那样,这种行为的讨厌之处在于它在不同平台上的表现是不一致的。当我看到你无法复现时,我尝试了不同的方法:奇怪的行为出现在我通常使用的Docker环境中,但在osx终端直接运行R时却没有出现。这很烦人。 - Vincent
1个回答

6
这是R正则表达式子系统中已知的故障,与输入的字符编码和系统语言环境/构建属性有关。
grep的R文档中指出(加粗部分):POSIX 1003.2模式的gsub和gregexpr在使用重复字边界(例如,pattern="\b")时无法正确工作。对于这种匹配,请使用perl=TRUE(但是,对于非ASCII输入,“word”的含义因系统而异可能无法按预期工作)。只提到了gsub和grepexpr,而grepl也可能受到影响。

可能的解决方案

  • using R's default (TRE reference) regex engine: PERL=FALSE as already discovered by you.
  • stick with the PCRE (reference) regex using the *UCP flag (Unicode mode|Unicode Character Properties), which changes the matching behavior so that Unicode alphanumerics are not considered as word boundaries:

    Code Sample:

    options(encoding = "UTF-8")
    
    test1 <- 'aland islands'
    test2 <- 'åland islands'
    regex1 <- "[å|a]land islands"
    regex2 <- "(*UCP)\\b[å|a]land islands"    
    grepl(regex1, test2, perl = TRUE)
    #[1] TRUE
    grepl(regex2, test2, perl = TRUE)
    #[1] TRUE
    grepl(regex1, test2, perl = TRUE)
    #[1] TRUE
    grepl(regex2, test2, perl = TRUE)
    #[1] TRUE
    grepl(regex1, test2, perl = FALSE)
    #[1] TRUE
    grepl(regex2, test2, perl = FALSE)
    #[1] FALSE
    

    Online Demo

    Notes:

    • The 6th test, using TRE with the (*UCP) flag, fails grepl(regex2, test2, perl = FALSE)

    • The *UCP flag does not work if R is not installed with Unicode support for PCRE (may be the case in some environments, e.g. some minimal Cloud/Docker installations).


令人讨厌的是,R在不同平台上的行为是不一致的:

  • 在当前64位Windows(10)上按预期工作
  • 可能在当前Linux发行版上工作

使用以下在线R环境测试您的原始代码:

  • tutorialspoint
  • Ideone

    只有测试用例4不正确:gepl(regex2, test2, perl = TRUE)
    (在Linux上运行R 3.3/3.4?)

  • JDoodle

    测试用例4和6不正确 (在Linux上运行R 3.3-3.5?)


更多阅读:


1
这是一个非常出色的答案。非常感谢您抽出时间写下这篇文章,我真的很感激。我会阅读所有这些链接,并在下次遇到类似问题时更加了解情况。 - Vincent

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