Регулярное выражение в php поиск всех совпадений в строке

У меня есть строка, это всегда строка с тегами proxy, core, error, get, но всегда имеющая разный порядок написания тегов. После тега всегда идет двоеточие, затем комментарий тега, все выглядит примерно так:

Core:init Proxy: Attemps is ended. Error: Proxy connect timeout Error: core unknown Core:error parse line

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

Core:init 
Proxy: Attemps is ended. 
Error: Proxy connect timeout 
Error:core unknown 
Core:error parse line
...

Используя следующую регулярное выражение (?>(?:core|proxy|error|get)\:(.+?)(?=(core|proxy|error|get)\:)) я получаю почти правильный результат, а точнее все совпадения без последнего вхождения. Я перепробовал массу вариантов написания регулярок и все они работают не правильно. Как мне заставить регулярное выражение ловить все совпадения в строке?

Пример: https://regex101.com/r/V97LNk/1

Еще варианты которые я пробовал: https://regex101.com/r/WzZ9A3/1 и https://regex101.com/r/xCJHOF/1

Так же я играл с PREG_SET_ORDER и PREG_PATTERN_ORDER в функции preg_match_all однако это не дало значимых изменений.


Ответы (1 шт):

Автор решения: Wiktor Stribiżew

Во-первых, уберите всё лишнее: атомарная группировка и экранирование перед двоеточиями не нужны.

Во-вторых, основная проблема — отсутствие альтернативы с концом строки: блок предварительного просмотра вперёд (?=(core|proxy|error|get):) требует наличия core, proxy, error или get, за которыми следует символ :, но если там конец строки, совпадения не будет.

Конец строки можно найти с помощью $ или \z (после этого не может быть ничего, даже символа LF в самом конце строки).

Используйте один из двух шаблонов:

(?:core|proxy|error|get):(.+?)(?=(core|proxy|error|get):|$)
(?:core|proxy|error|get):(.+?)(?=(core|proxy|error|get):|\z)

См. пример работы выражения.

Возможно, вам больше подойдёт

(core|proxy|error|get):\s*\K.+?(?=\s*(?1):|\z)

См. пример работы выражения.

Подробности

  • (core|proxy|error|get) - Захватывающая подмаска №1: одно из указанных слов
  • : - двоеточие
  • \s* - ноль и более пробельных символов
  • \K - оператор, очищающий буфер текущего совпадения (весь текст, найденный до сих пор, удаляется из этого буфера)
  • .+? - один и более символов, отличных от перевода строки, как можно меньше
  • (?=\s*(?1):|\z) - блок предварительного просмотра вперёд, который требует наличия ноля и более пробельных символов (\s*), последовательности шаблонов, заданных в подмаске №1 ((?1)), а затем :, или | конец строки \z (можно использовать $ тоже).
→ Ссылка