Многострочный PCRE w\ lookhead, count matches

Я пытаюсь выполнить regex, который соответствует, если оба слова cat И dog находятся в regex с многострочной поддержкой

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

Regex, который я использую, довольно прост

/^(?=.*\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 regex все равно находит совпадение до конца.

2
задан 15 September 2017 в 00:03
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 +.

0
ответ дан 3 December 2019 в 14:09

Теги

Похожие вопросы