Назад | Перейти на главную страницу

Многострочный PCRE с просмотром, подсчет совпадений

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

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 регулярное выражение все еще соответствует до конца.

Некоторые подсказки, но не полный ответ.

.* с участием /s собирается съесть все до конца строки. Переход на не жадный .*? хотя будет соответствовать минимальной строке; опережающие просмотры не включаются в совпадение. Моя обычная стратегия обработки заключается в том, чтобы включить якоря в опережающие просмотры, но многострочное сопоставление затрудняет это.

/m потребуется, если вы хотите найти несколько раз в одной строке и по-прежнему использовать ^$ якоря. В противном случае они соответствуют только началу и концу строки.

Если вам действительно не нужно решение для общего случая, вероятно, стоит попробовать вручную упорядочить свои подшаблоны, например:

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

Есть несколько действительно интересных вещей, которые вы можете сделать с рекурсивными подшаблонами и относительными обратными ссылками, но я не смог структурировать их в общий случай для N предпросмотра без увеличения количества шагов до 10k + диапазона.