Сопоставьте каждый элемент между двумя словами в списке, разделенном запятыми

#regex #pcre

Вопрос:

У меня есть числа, разделенные запятыми, я хочу сопоставить каждый элемент после START или до END , если существует какое-либо ключевое слово.

Я правильно понял большинство тестовых случаев, используя

 (?:.*?START|END.*)(*SKIP)(*F)|d 
 

за исключением тех, которые START появляются после END или нескольких экземпляров START и END существуют.

вход Матчи
123,45678,789,777,888,1234 123 , 45678 , 789 , 777 , 888 , 1234
123,START,789,777,888,1234 789 , 777 , 888 , 1234
123,45678,789,777,END,1234 123 , 45678 , 789 , 777
123,START,789,777,END,1234 789 , 777
123,END,789,777,START,1234 123
123,START,789,START,777,END,1234 789 , 777
123,START,789,END,777,END,1234 789
123,END,789,START,777,END,1234 123

Вот проект regex101, который я пробовал, я использую PCRE2(PHP7.3).

Комментарии:

1. Вы можете уточнить 123,START,789,START,777,END,1234 требования?

2. Что непонятно? 789 и 777 ожидаются, поскольку они появляются после первого появления START и до первого появления END .

3. @anubhava, пока их несколько START или END существует. Всегда используйте первый и игнорируйте дальнейшие экземпляры.

Ответ №1:

Вы можете исправить свой шаблон, добавив ограничение, чтобы найти START то, чего END до него не было:

 (?:^(?:(?!END).)*?START|END.*)(*SKIP)(*F)|d 
// ^^^^^^^^^^^^^^^
 

Смотрите демонстрацию регулярных выражений.

Здесь ^(?:(?!END).)*?START (вместо .*?START ) совпадений

  • ^ — начало строки
  • (?:(?!END).)*? — любые символы, кроме символов разрыва строки, как можно меньше, которые не запускают последовательность END символов
  • START START последовательность символов.

Вы также можете использовать

 (?:G(?!A)|^(?:(?:(?!END).)*?START)?)(?:(?!END).)*?Kd 
 

Смотрите демонстрацию регулярных выражений.

Подробные сведения:

  • (?:G(?!A)|^(?:(?:(?!END).)*?START)?) — либо конец предыдущего успешного совпадения ( G(?!A) ), либо ( | ) начало строки ( ^ ), а затем необязательное вхождение любого текста до первого вхождения START , которому не предшествует END ( (?:(?:(?!END).)*?START)? )
  • (?:(?!END).)*? — любой символ, кроме символов разрыва строки, ноль или более раз, но как можно меньше, который не запускает последовательность END символов
  • K — оператор сброса соответствия, который удаляет весь текст, сопоставленный до сих пор, из общего буфера памяти соответствия
  • d — одна или несколько цифр.