代码之家  ›  专栏  ›  技术社区  ›  moodymudskipper

字符串是相同的(使用'base::equality`),但在'grepl`/'gsub中的行为不同`

  •  9
  • moodymudskipper  · 技术社区  · 6 年前

    相关: Convert upper case words to title case

    某些使用从联机获取的字符串的代码的行为与我预期的不同,您可以通过运行以下命令重现此问题:

    library(xml2)
    library(magrittr)
    x <- xml2::read_html("https://poesie.webnet.fr/lesgrandsclassiques/Authors/B") %>%
      gsub("^.*?<span>(Pierre-Jean de BÉRANGER)</span>.*$","\\1",.)
    x # [1] "Pierre-Jean de BÉRANGER"
    

    此字符串与 "Pierre-Jean de BÉRANGER" 从页面源复制/粘贴,但是以下行为对我非常不安:

    y <- "Pierre-Jean de BÉRANGER"
    x == y  # TRUE
    identical(x, y) # TRUE
    gsub("\\b([A-Z])(\\w+)\\b", "\\1\\L\\2", x, perl = TRUE) # [1] "Pierre-Jean de BÉRANGER"
    gsub("\\b([A-Z])(\\w+)\\b", "\\1\\L\\2", y, perl = TRUE) # [1] "Pierre-Jean de Béranger"
    grepl("\\bB\\w+", x, perl = TRUE) # FALSE
    grepl("\\bB\\w+", y, perl = TRUE) # TRUE
    grepl("\\bB\\w", x, perl = TRUE)  # TRUE
    grepl("\\bB\\w", y, perl = TRUE)  # TRUE
    

    如果 x y 是一样的,怎么会有不同的输出呢?

    ?identical :

    测试两个物体的安全可靠方法 平等的


    编辑:

    这里有一个明显的区别:

    Encoding(x) # "UTF-8"
    Encoding(y) # "latin1"
    

    我在跑步 R version 3.5.0 Windows

    3 回复  |  直到 6 年前
        1
  •  2
  •   MrFlick    6 年前

    如果你查看 source of the identical() function ,当它通过 CHARSXP Seql() . 那个功能 converts string values to UTF identical 不是检查编码是否一定相同,而是检查编码中的值embded是否相同。

    identical() 函数应具有 ignore.encoding=

    但理论上,弦的行为应该是一样的。因此,我想您可以责怪这里的regexpr引擎的“perl”版本没有正确处理编码。基本regexpr引擎似乎没有这个问题

    grepl("B\\w+", x)
    # [1] TRUE
    grepl("B\\w+", y)
    # [1] TRUE
    
        2
  •  5
  •   Wiktor Stribiżew    6 年前

    为了克服这个问题,您需要确保您的模式能够识别Unicode,以便 \w 可以匹配所有Unicode字母和数字 \b 无法在Unicode字词边界处匹配。这可以通过使用PCRE动词来实现 (*UCP) :

    gsub("(*UCP)\\b([A-Z])(\\w+)\\b", "\\1\\L\\2", x, perl = TRUE)
          ^^^^^^
    

    \p{Lu} 而不是 [A-Z]

    gsub("(*UCP)\\b(\\p{Lu})(\\w+)\\b", "\\1\\L\\2", x, perl = TRUE)
    

    另外,如果您不想匹配数字和 _ ,您可以替换 具有 \p{L} (任何字母):

    gsub("(*UCP)\\b(\\p{Lu})(\\p{L}+)\\b", "\\1\\L\\2", x, perl = TRUE)
    
        3
  •  1
  •   moodymudskipper    6 年前

    现在看一下工作流程,我相信在实践中,最好确保始终知道一个人使用的是什么编码,并且在任何可以接受的情况下,在导入/获取步骤或之后协调所有内容。

    在上述情况下,没有理由不在检索外部数据后立即协调编码,以避免出现这种糟糕的意外情况。

    x <- iconv(x, from="UTF-8", to="latin1")