R正则表达式:将\\ b与'Å'与'A'字符一起使用

时间:2018-07-22 23:42:54

标签: r regex

\\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

1 个答案:

答案 0 :(得分:4)

这是R的regex子系统中的(已知)故障,与输入的字符编码和系统区域设置/内置属性有关。

grep上的R文档指出(已突出显示):

  

gsub和gregexpr的POSIX 1003.2模式无法正常工作   具有重复的单词边界(例如pattern =“ \ b”)。使用perl = TRUE   对于此类匹配(,但对于非ASCII可能无法正常工作   输入,因为“单词”的含义取决于系统)。

这里仅提及gsubgrepexprgrepl似乎也受到影响。

可能的状态

  • 使用您已经发现的R的默认(TRE reference)正则表达式引擎:PERL=FALSE
  • 使用*UCP标志(Unicode模式| Unicode字符属性)使用PCRE(reference)正则表达式,它会更改匹配行为,因此Unicode字母数字不被视为单词边界:

    代码示例:

    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

    注意:

    • 将TRE与(* UCP)标志一起使用的第六次测试未通过grepl(regex2, test2, perl = FALSE)

    • 如果未在R中安装对PCRE的Unicode支持,则*UCP标志不起作用(在some environments中可能是这种情况,例如某些最小的Cloud / Docker安装)。


真正令人讨厌的是R的行为在各个平台上是不一致的:

  • 在当前的64位Windows(10)上可以正常工作
  • 可以在当前的Linux发行版上工作

在这些在线R环境中测试原始代码:

  • tutorialspoint
  • Ideone

    只有测试案例4为FALSE:gepl(regex2, test2, perl = TRUE)
    (在Linux上运行R 3.3 / 3.4吗?)

  • JDoodle

    测试用例4和6为FALSE (在Linux上运行R 3.3-3.5吗?)


更多读数: