R:可变宽度后视的解决方法

R: workaround for variable-width lookbehind

给出这个向量:

ba <- c('baa','aba','abba','abbba','aaba','aabba')'

除了baaaba,我想把每个词的词尾a改成i

我写了下面这行...

gsub('(?<=a[ab]b{1,2})a','i',ba,perl=T)

但被告知:PCRE 模式编译错误 'lookbehind assertion is not fixed length' 在 ')a'

我环顾四周,显然 R/Perl 只能向前看可变宽度,不能向后看。这个问题有什么解决方法吗?谢谢!

您可以改用回顾替代方案 \K。此转义序列重置报告匹配的起点,并且不再包括任何先前使用的字符。

引用rexegg

The key difference between \K and a lookbehind is that in PCRE, a lookbehind does not allow you to use quantifiers: the length of what you look for must be fixed. On the other hand, \K can be dropped anywhere in a pattern, so you are free to have any quantifiers you like before \K.

在上下文中使用它:

sub('a[ab]b{1,2}\Ka', 'i', ba, perl=T)
# [1] "baa"   "aba"   "abbi"  "abbbi" "aabi"  "aabbi"

避免环顾四周:

sub('(a[ab]b{1,2})a', '\1i', ba)
# [1] "baa"   "aba"   "abbi"  "abbbi" "aabi"  "aabbi"

另一种解决方案仅适用于当前情况,当使用的唯一量词是 limiting quantifier 时,可能会使用 stringr::str_replace_all / stringr::str_replace :

> library(stringr)
> str_replace_all(ba, '(?<=a[ab]b{1,2})a', 'i')
[1] "baa"   "aba"   "abbi"  "abbbi" "aabi"  "aabbi"

之所以有效,是因为 stringr 正则表达式函数基于 ICU regex,具有 constrained-width 后视:

The length of possible strings matched by the look-behind pattern must not be unbounded (no * or + operators.)

因此,您不能真正在 ICU 后视中使用任何类型的模式,但很高兴知道当您需要在已知距离范围内获取重叠文本时,您至少可以在其中使用一个限制量词。