多行 PCRE,带 lookhead,计数匹配

多行 PCRE,带 lookhead,计数匹配

我正在尝试执行一个正则表达式,如果单词 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,正则表达式仍然匹配直到最后。

答案1

有一些提示,但不是完整的答案。

.*with/s会吃掉所有东西直到字符串结束。.*?但是切换到非贪婪模式会匹配最小字符串;前瞻不会被强制纳入匹配。我通常的处理策略是在前瞻中包含锚点,但多行匹配会让这变得困难。

/m如果您想在同一个字符串中多次匹配并且仍然使用锚点,则需要使用^$。否则它们仅匹配字符串的开头和结尾。

除非您确实需要一般情况的解决方案,否则可能值得尝试手动排序子模式,例如:

(?gsmx)(?(DEFINE)
  (?<a>\bcat\b)
  (?<b>\bdog\b)
)
^.*?(?:
      (?&a).*?(?&b)|  # cat before dog
      (?&b).*?(?&a)   # dog before cat
    )[^\n]*
$

使用递归子模式和相对反向引用可以做一些非常有趣的事情,但是我无法将它们构建为 N 前瞻的一般情况,因为步骤数不会飙升到 10k+ 范围。

相关内容