stringr、str_extract:如何进行正向回顾后断言?

11

这是一个非常简单的问题。我只需要使用正则表达式中的正向后查找来捕获一些字符串,但是我不知道如何实现。

以下是一个例子,假设我有一些字符串:

library(stringr)
myStrings <- c("MFG: acme", "something else", "MFG: initech")

我想提取以"MFG:"为前缀的单词。

> result_1  <- str_extract(myStrings,"MFG\\s*:\\s*\\w+")
>
> result_1
[1] "MFG: acme"    NA             "MFG: initech"

这几乎完成了,但我不想包含"MFG:"部分,这就是"positive lookbehind"的作用:

> result_2  <- str_extract(myStrings,"(?<=MFG\\s*:\\s*)\\w+")
Error in stri_extract_first_regex(string, pattern, opts_regex = attr(pattern,  : 
  Look-Behind pattern matches must have a bounded maximum length. (U_REGEX_LOOK_BEHIND_LIMIT)
> 

它抱怨需要一个“有界最大长度”,但我不知道在哪里指定。如何让正向先行断言起作用?确切地说,在哪里可以指定这个“有界最大长度”?


啊哈!Stringr的正则表达式需要对回顾限制进行限制! - Angelo
除了Wiktor在下面的答案中所述的情况外,大多数环视都是固定宽度的,因此您不能使用量词。 - alistaire
3个回答

12

由于“向后查找”的模式是一个文字,而且您不知道空格的数量,因此需要使用str_match

> result_1  <- str_match(myStrings,"MFG\\s*:\\s*(\\w+)")
> result_1[,2]
##[1] "acme"    NA        "initech"

你需要的结果将在第二列中。请注意,此处不能使用str_extract函数,因为该函数会删除捕获的值。另外一个小提示:ICU正则表达式中的回顾后发断言不是无限宽度的,但它是有限宽度的。因此,以下代码也可以使用:
> result_1  <- str_extract(myStrings,"(?<=MFG\\s{0,100}:\\s{0,100})\\w+")
> result_1
[1] "acme"    NA        "initech"

1
我现在明白了,谢谢!如果我无法限制回顾区的大小,这就是我需要做的。 - Angelo
哇,我不知道你可以在stringr正则表达式中使用 {} 来量化环视;那很令人兴奋。但这在基本或者 perl = TRUE 正则表达式中是会失败的。 - alistaire
这就是为什么它被称为受限宽度的向后查找:如果长度可以计算(并且使用具有最小和最大值的限定符是可能的),则可以使用它。 - Wiktor Stribiżew

5
我们可以使用正则表达式的lookaround来实现,lookbehind只匹配完全相同的内容。
str_extract(myStrings, "(?<=MFG:\\s)\\w+")
#[1] "acme"    NA        "initech"

谢谢!是的,我的正则表达式在.NET中起作用了,但R的正则表达式有点不同!现在 \s* 是问题所在是有意义的。 - Angelo
1
没有通用的 R 正则表达式,不同的模块使用不同的风格。有 TRE、PCRE 和 ICU 正则表达式风格。 - Wiktor Stribiżew
@WiktorStribiżew,很遗憾,我不可能全都知道。只能在某些东西停止工作之前硬着头皮去尝试。 - Angelo

0

我使用了Python中的lookbehind编写了这段代码。如果解析器找到MFG:,它将获取下一个单词。

txt="MFG: acme, something else, MFG: initech"
pattern=r"(?<=MFG\:)\s+\w+"
matches=re.findall(pattern,txt)
for match in matches:
   print(match)

输出:

 acme
 initech

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