preg_match_all - жадная часть регулярного выражения, но максимизировать количество совпадений - PullRequest
1 голос
/ 03 марта 2011

У меня есть следующий html для разбора:

<h1 class="x">test</h1>
<p>some text <img src="x" /></p>

<h1 class="x1">test2</h1>
<p>some text </p>

<h1 class="2">test3</h1>
<p>some text <img src="x" /></p>

Можно ли разобрать это в массив с одним регулярным выражением?

Я пытался

preg_match_all('#(<h1[^>]*?>)(.*?)(</h1>)(.*)#ism',$html,$arr);

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

preg_match_all('#(<h1[^>]*?>)(.*?)(</h1>)(.*?)#ism',$html,$arr);

, который не дает мне ничего о HTML между <h1>, потому что выражение не жадное.

Как я могу сделать деталь после сопоставления жадной, и в то же время сопоставить как можно больше вхождений?

Дополнительные комментарии:

  • вопрос довольно академический, я решил проблему с помощью pre_split, и множество других методов сработало бы, но может иметь и недостатки (например, DOM может не работать с недопустимым HTML, который я не могу контролировать). Однако это повторяющаяся проблема, о которой мне было бы интересно узнать больше.

Ответы [ 2 ]

4 голосов
/ 03 марта 2011

Вам нужна какая-то форма конечного создателя. Регулярное выражение не может угадать, до какой части вы хотите соответствовать.

Возможным в этом случае может быть предвкушение после (.*?) в конце:

(?=<h1|</body>|\z)#ims
1 голос
/ 03 марта 2011

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

Соответствующие части шаблона:

  • Ленивый : .*?(?=<h1|\z)
  • Жадный : (?:[^<]+|<(?!h1))*

Возможно, вы знакомы с Производительность жадных и ленивых квалификаторов в целом , но суть здесь намного проще.

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

Однако в HTML у вас гораздо больше других символов, чем < символов, поэтому жадный шаблон, который не имеетпроверка других символов может быть на несколько порядков быстрее.

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

...