如何在R中使用grep的反向引用?

15
我希望在R中使用正则表达式寻找以月份名称开头的字符串,并以一种简洁的方式返回相关引用。让我解释一下:
x <- c("May, 1, 2011", "30 June 2011")
grep("May|^June", x, value=TRUE)
[1] "May, 1, 2011"

这个方法可以实现功能,但我想要的是只提取月份(比如说“五月”而不是整个被匹配到的字符串)。

所以,可以使用 gsub 函数并设置 substitute 参数来返回反向引用。但这种方法有两个问题:

  1. 你需要将匹配模式包含在 ".*(pattern).*)" 中,以便替换出整个字符串。
  2. gsub 函数会返回原始字符串而非 NA 值,对于未匹配到的字符串这显然不是我想要的结果:

代码和结果如下:

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

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

明确的是,期望的结果应该是:

[1] "May"          NA

有没有一种简单的方法可以实现这个?

3个回答

20

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"

非常好的建议,谢谢。最终,我决定接受Hadley的答案,因为它更加优雅。 - Andrie

9

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函数更加一致来使得字符串处理更加容易。


1
谢谢,Hadley。我总体上非常喜欢stringr。我不知道为什么我没有想到先在那里搜索。D'oh。 - Andrie

3

gsubfn包比grep和regexpr函数更通用,并具有使您返回backrefrences的方法,请参见strapply函数。


1
尝试一下:library(gsubfn); strapply(x, "^(五月|六月)") - G. Grothendieck

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