Регулярное выражение с несколькими группами захвата

#php #regex

#php #регулярное выражение

Вопрос:

Я работал над регулярным выражением, чтобы выделить кучу текстовых файлов, которые мне нужно разобрать в базе данных. Мои файлы находятся в следующем формате:

 Lorem ipsum doloramp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;amp;nbsp;sit amet, consectetur adipiscing elit.

Fusce lacinia sollicitudin lectus id eleifend. Phasellus.

massa sapien, scelerisque in tincidunt et, porttitor eget ante.
In iaculis justo vel quam rhoncus volutpat. Curabitur eros est,
ultrices in elementum eget, venenatis eget mauris. Sed sollicitudin,
nibh sed varius aliquet, neque odio porttitor risus, at sollicitudin

lectus neque sit amet diam.
Aliquam condimentum sapien eu
tellus condimentum suscipit.
Pellentesque in accumsan nunc.
  

Я пытаюсь создать следующие группы захвата:

  • Lorem ipsum dolor
  • sit amet, consectetur adipiscing elit.
  • Fusce lacinia sollicitudin lectus id eleifend. Phasellus.
  • massa sapien, scelerisque in tincidunt et, porttitor eget ante.
    In iaculis justo vel quam rhoncus volutpat. Curabitur eros est,
    ultrices in elementum eget, venenatis eget mauris. Sed sollicitudin,
    nibh sed varius aliquet, neque odio porttitor risus, at sollicitudin

Примечания: Все, что находится после многострочного абзаца, может быть проигнорировано. Все группы могут включать буквы, цифры, пробелы и знаки препинания. Я собираюсь выполнить некоторую дополнительную постобработку текста с использованием PHP.

Моя последняя попытка захватить первые 2 части, которая была ближе, чем мои другие попытки, но все равно не сработала так, как предполагалось, была:

 ^((?:[a-zA-Z0-9!-~](?: (?! ))?) ?)(?: {2,})((?:[a-zA-Z0-9!-~](?: (?! ))?) ?)
  

Я думал, что это начнется с начала файла, захватит все вплоть до точки, где встречается несколько пробелов, а затем захватит остальную часть строки.

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

1. Я использую PHP для выполнения всего.

2. Просто чтобы знать. Это полезно при задании вопросов о регулярных выражениях.

3. используйте nl2br() для строки и затем preg_match_all() с некоторой логикой .. 🙂

Ответ №1:

Попробуйте это:

 $pattern='~A(. ?) {2,}(. ?)R{2,}(. ?)R{2,}(. ?)(?:R{2,}|Z)~s';

preg_match($pattern, $subject, $match);
  

Посмотрите это в действии на ideone.com

Я предполагаю, что все эти amp;nbsp; в вашем примере текста представляют собой обычные пробелы, и вы использовали их только для того, чтобы мы могли видеть, что там было больше одного пробела. Если бы вы использовали форматирование кода SO с самого начала, в этом не было бы необходимости. Это стиль форматирования с отступом; в тексте, отформатированном с обратными метками, пробелы по-прежнему сворачиваются.

Я также предполагаю, что вы считываете весь файл в память, а не обрабатываете его построчно. Регулярное выражение довольно простое. Начиная с начала текста ( A ), оно неохотно сопоставляет и фиксирует все, что видит ( (. ?) в однострочном режиме), пока не увидит два или более последовательных пробела ( {2,} ).

После этого он неохотно выполняет сопоставление и захват, пока не увидит два или более перевода строки подряд ( (. ?)R{2,} ). Затем он делает то же самое еще дважды, чтобы захватить второй и третий абзацы. Последнее (?:R{2,}|Z) есть на случай, если после третьего абзаца больше нет текста.

R , если вы с ним не знакомы, является сокращением для любого вида разделителя строк: n , r , rn и нескольких других, менее распространенных. Оно поддерживается Perl, PHP (PCRE), Ruby 1.9 (Oniguruma) и несколькими другими вариантами, но не (пока) JavaScript, Python, Java или .NET.

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

1. Я использовал модифицированную версию приведенного выше шаблона: code /^(.*?) {2,}(.*?) t(.*?)t(.*?) t/s