可变长度的后视镜

时间:2014-08-29 07:51:43

标签: regex perl

是否有任何优雅的解决方案来构建可变长度的后视正则表达式,例如这个?

/(?<=eat_(apple|pear|orange)_)today|yesterday/g;

似乎Perl有一个非常令人印象深刻的正则表达式引擎和可变长度lookbehind将是非常有趣的。有没有办法让它发挥作用,还是我应该忘记这个坏主意?

7 个答案:

答案 0 :(得分:16)

使用\K作为特例。

这是一个可变长度的正向后视断言:

/eat_(?:apple|pear|orange)_\Ktoday|yesterday/g

或者,您可以单独列出您的lookbehind断言:

/(?:(?<=eat_apple_)|(?<=eat_pear_)|(?<=eat_orange_))today|yesterday/g

但是,我建议它可能是一个罕见的问题,可能会使用该功能,但无法重新考虑使用其他更常见的正则表达式功能的组合。

换句话说,如果您遇到特定问题,请随时在此处分享,我确信有人可以提出不同的(可能更好的)方法。

答案 1 :(得分:5)

怎么样:

(?:(?<=eat_apple_)|(?<=eat_pear_)|(?<=eat_orange_))(today|yesterday)

有点uggly,但它确实有效。

答案 2 :(得分:3)

您可以使用预测而不是后视:

/(?:eat_(apple|pear|orange)_)(?=today|yesterday)/g

总的来说,有一种替代方式来描述天真似乎需要后视的东西。

答案 3 :(得分:1)

替代解决方案-反转字符串并改用lookahead。不得不反向写模式词看起来很丑,但是当其他所有方法都失败时,这是一个选择。

答案 4 :(得分:0)

今天发现的博客帖子,在#regex @ irc.freenode.org上与我链接:

http://www.drregex.com/2019/02/variable-length-lookbehinds-actually.html

本文介绍了如何在PCRE中进行可变宽度的后视。

解决方案将是:

/(?=(?=(?'a'[\s\S]*))(?'b'eat_(?:apple|pear|orange)_(?=\k'a'\z)|(?<=(?=x^|(?&b))[\s\S])))today|yesterday/g

https://regex101.com/r/9DNpFj/1

答案 5 :(得分:0)

Perl v5.30 在正则表达式引擎知道长度为 255 个字符或更少的情况下添加了 experimental variable-width lookbehinds(例如,没有无限量词)。

现在可以使用了:

use v5.30;
use experimental qw(vlb);

$_ = 'eat_apple_today';
say "Matched!" if /(?<=eat_(apple|pear|orange)_)today|yesterday/g;

答案 6 :(得分:-1)

对我有用的解决方案:
暂时使长度可变的任何长度固定。

在这种情况下:
将您所有的 'eat_apple's、'eat_pear's 和 'eat_orange's 更改为类似eat_fruit 的内容,然后以可接受的固定长度后视方式运行您想到的表达式。尽管它需要两遍和一些内存,但我发现代码方式更容易阅读,而且它可能比其他一些解决方案更快。