【问题标题】:How can I use back references with `grep` in R?如何在 R 中使用带有 `grep` 的反向引用?
【发布时间】:2011-09-06 03:51:33
【问题描述】:

我正在寻找一种在 R 中使用正则表达式返回引用的优雅方式。让我解释一下:

假设我想查找以月份名称开头的字符串:

x <- c("May, 1, 2011", "30 June 2011")
grep("May|^June", x, value=TRUE)
[1] "May, 1, 2011"

这可行,但我真的想隔离月份(即“May”,而不是整个匹配的字符串。

因此,可以使用gsub 使用substitute 参数返回反向引用。但这有两个问题:

  1. 您必须将模式包装在“.*(pattern).*)”中,以便替换发生在整个字符串上。
  2. gsub 不是为不匹配的字符串返回 NA,而是返回原始字符串。这显然不是我想要的:

代码和结果:

gsub(".*(^May|^June).*", "\\1", x) 
[1] "May"          "30 June 2011"

我可能可以通过执行各种额外检查来编写解决方法,但这很快就会变得非常混乱。

为了一目了然,期望的结果应该是:

[1] "May"          NA

有没有简单的方法来实现这一点?

【问题讨论】:

    标签: r regex


    【解决方案1】:

    regexpr 类似于grep,但返回每个字符串中(第一个)匹配的位置和长度:

    > x <- c("May, 1, 2011", "30 June 2011", "June 2012")
    > m <- regexpr("May|^June", x)
    > m
    [1]  1 -1  1
    attr(,"match.length")
    [1]  3 -1  4
    

    这意味着第一个字符串在位置 1 有一个长度为 3 的匹配,第二个字符串没有匹配,第三个字符串在位置 1 有一个长度为 4 的匹配。

    要提取匹配项,您可以使用以下内容:

    > m[m < 0] = NA
    > substr(x, m, m + attr(m, "match.length") - 1)
    [1] "May"  NA     "June"
    

    【讨论】:

    • 很好的建议,谢谢。最后还是决定接受哈德利的回答,只是因为它更优雅。
    【解决方案2】:

    gsubfn 包比 grep 和 regexpr 函数更通用,并且具有返回反向引用的方法,请参阅 strapply 函数。

    【讨论】:

    • 试试这个:library(gsubfn); strapply(x, "^(May|June)").
    【解决方案3】:

    stringr 包有一个专门用于此目的的功能:

    library(stringr)
    x <- c("May, 1, 2011", "30 June 2011", "June 2012")
    str_extract(x, "May|^June")
    # [1] "May"  NA     "June"
    

    它是 regexpr 的一个相当薄的包装器,但 stringr 通常比基本 R 函数更一致,从而使字符串处理更容易。

    【讨论】:

    • 谢谢,哈德利。总的来说,我是 stringr 的忠实粉丝。我不知道为什么我没有想到先在那里搜索。哦。
    猜你喜欢
    • 2011-05-22
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2022-09-23
    • 2021-11-23
    • 2018-07-25
    相关资源
    最近更新 更多