str_extract_all返回不匹配的组

时间:2013-08-29 15:22:29

标签: regex r perl stringr

我正在尝试使用str_extract_all包中的stringr从R中的某些文本中提取值,我想使用perl的regexps (?:...)中的非匹配组来提取并在一行中清除相关值。

运行此代码时:

library(stringr)

## Example string.
## Not the real string, but I get the same results with this one.
x <- 'WIDTH 4\nsome text that should not be matched.\n\nWIDTH   46 some text.'

## extract values
str_extract_all(x, perl('(?:WIDTH\\s+)[0-9]+'))

我想得到这个结果:

[[1]]
[1] "4"    "46"

但我明白了:

[[1]]
[1] "WIDTH 4"    "WIDTH   46"

我做错了什么?

2 个答案:

答案 0 :(得分:5)

正则表达式仍匹配WIDTH - 它只是没有将它放入捕获组。你的正则表达式相当于

WIDTH\s+[0-9]+

您的代码会提取正则表达式匹配的整个子字符串。 (非)捕获组不会改变它。

您可以使用lookbehind声明某个字符串位于当前位置之前,而不将其包含在匹配的子字符串中:

(?<=WIDTH\s)[0-9]+

根据确切的正则表达式引擎,您不能在lookbehind中使用可变长度模式。还有另一种形式可以允许:

WIDTH\s+\K[0-9]+

答案 1 :(得分:2)

perl零宽度正则表达式是错误的。

以下是不需要perl正则表达式的解决方案:

sub("WIDTH\\s+", "", str_extract_all(x, 'WIDTH\\s+[0-9]+')[[1]])

或更简单:

library(gsubfn)
strapplyc(x, "WIDTH\\s+(\\d+)")

此外,如果我们希望将结果返回为数字,则可以使用:

strapply(x, "WIDTH\\s+(\\d+)", as.numeric)