Как решить жадное регулярное выражение - PullRequest
2 голосов
/ 04 июля 2019

У меня проблема с регулярным выражением в PHP.

Этот текст должен быть обработан:

Start Text1
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
End Text1
Start Text2
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
End Text2

Я хотел бы добавить

к строкам.

Я пытаюсь это, с этой скороговоркой:

(?!<\/li>)\s*(<li>.*</li>)\s*(?=<li>|)

Но выдает что-то вроде этого:

Start Text1
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
End Text1
Start Text2
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
End Text2

... также включены «Конец текста1» и «Начать текст2». Поэтому я предпочитаю получить такой результат:

Start Text1
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
End Text1
Start Text2
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
End Text2

Как я могу это сделать?

Я проверял это здесь: https://www.phpliveregex.com/p/sHs#tab-preg-replace

1 Ответ

2 голосов
/ 04 июля 2019

Исправление регулярного выражения

Это регулярное выражение работает:

(\s*<li>.*?<\/li>\s*)(?!\s*<li>)

Объяснение:

  • .*? просит регулярное выражение:как можно меньше совпадать между <li> и </li>, чтобы оно прекратилось, как только будет текст, не входящий в <li>;
  • Я избежал / во втором случае </li>, как вы уже сделали в первом случае;
  • (?!\s*<li>) говорит, что следующий бит текста не может быть другим <li> - необходим, потому что в противном случае .*? выше делает его соответствующим каждой строке <li> отдельно;
  • первоначальный (?!<\/li>) на самом деле ничего не делает, поэтому я удалил его.

Более удобная обработка новых строк

Вкл.на веб-сайте Live Regex я не смог вставить новые строки там, где хотел.

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

preg_replace('/\s*(<li>.*?<\/li>)\s*(?!\s*<li>)/smi',
   "\n<ul>\n$1\n</ul>\n", $input)

или

preg_replace('/(\s*<li>.*?<\/li>\s*)(?!\s*<li>)/smi',
   "\n<ul>$1</ul>\n", $input)

чтобы получить более хорошие результаты.Ключ заключается в том, чтобы поместить шаблон замены в двойные кавычки.

Лучшая обработка ввода с отступом

Если ввод был с отступом, вы также можете рассмотреть что-то вроде этого:

preg_replace('(\s*)(<li>.*?<\/li>)(\s*)(?!\s*<li>)/smi',
   "$1<ul>$1$2$1</ul>$3", $input)

это установит <ul> и </ul> на тот же уровень отступа, что и первый <li>, и сохранит окружающий текст на том же отступе, что и раньше.

Но, очевидно, ни одинэто действительно важно, учитывая, что все эти интервалы не изменят интерпретацию получающегося HTML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...