【问题标题】:Multi-line PCRE w\ lookahead, issue counting matches多行 PCRE w\lookahead,问题计数匹配
【发布时间】:2018-02-23 23:41:29
【问题描述】:

我正在尝试执行一个匹配的正则表达式,如果单词 cat 和 dog 都在正则表达式中,并且具有多行支持的任意顺序

matches

cat asdjfaldsfj dog
####
does NOT match

cat adfasdf8989
####
matches

dog adlsjf88989 cat
####
matches

cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf

我使用的正则表达式非常简单

/^(?=.*\bcat\b)(?=.*\bdog\b).*$/gs

问题是这只找到第一次出现,因为它是贪婪的。我真的希望以下计算两个匹配项,但它只匹配一次

cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf
cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf

即使没有第二组 cat STUFF dog STUFF,正则表达式仍然匹配到最后。

我正在使用 regex101.com 进行测试。

【问题讨论】:

  • 这是 Perl 还是 PCRE?你标记了两者,说 PCRE,但是使用 Perl 匹配操作符。

标签: regex perl optimization pcre


【解决方案1】:

主要问题不在于您使用了贪婪的量词;那是您正在使用^ 锚以及前瞻和.*。该模式将别无选择,只能匹配所有内容或不匹配任何内容。

相反,只需放弃前瞻方法并将 catdog 与两者之间的任何内容匹配,或者相反:

/cat.*?dog|dog.*?cat/gs

在这种情况下,您实际上确实需要使用 ? 指定惰性量词,否则它将像您担心的那样将所有匹配项当作一个匹配项来抓取。

https://regex101.com/r/nv9Nj7/1

【讨论】:

  • “猫”和“狗”就是一个例子。假设我想以任意顺序查找“cat”、“dog”、“bird”、“fish”。然后我将不得不进行前瞻或大量排列。
  • 啊,以为你最多只有两个。在那种情况下,是的,这个解决方案的可扩展性不是很高。
【解决方案2】:

只是一个建议,但也许这比复杂的正则表达式更具可读性

use List::MoreUtils 'all';

my @things = qw( cat dog bird fish );

for my $line ( @lines ) {
    if ( all { $line =~ / \b $_ \b /x } @things ) {
        # DO STUFF
    }
}

all 函数是List::MoreUtils 的一部分,但也可用于List::AllUtilsList::SomeUtils

这个实现依赖于你逐行处理你的字符串,所以你可能会做类似for my line ( split(/\n/, $string) ) { ... }的事情

【讨论】:

    【解决方案3】:

    CAustin 的回答可以简化为:

    /(cat|dog).*?(?!\1)(?:cat|dog)/gs
    

    这更容易扩展到更多的字符串。有 4 个字符串:

    /(cat|dog|bird|fish).*?(?!\1)(cat|dog|bird|fish).*?(?!\1|\2)(cat|dog|bird|fish).*?(?!\1|\2|\3)(?:cat|dog|bird|fish)/gs
    

    并限制一些无用的回溯:

    /(cat|dog|bird|fish)(?>.*?(?!\1)(cat|dog|bird|fish))(?>.*?(?!\1|\2)(cat|dog|bird|fish))(?>.*?(?!\1|\2|\3)(?:cat|dog|bird|fish))/gs
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多