Регулярное выражение для соответствия содержимого до многосимвольной строки - PullRequest
3 голосов
/ 15 июня 2011

Я получил дефектный вход, который выглядит так ...

foo<p>bar</p>

И я хочу нормализовать его, чтобы обернуть ведущий текст в тег p:

<p>foo</p><p>bar</p>

Это достаточно легко с заменой регулярного выражения /^([^<]+)/ на <p>$1</p>. Проблема в том, что иногда ведущий блок содержит теги, отличные от p, например:

foo <b>bold</b><p>bar</p>

Это должно обернуть весь кусок в новый p:

<p>foo <b>bold</b></p><p>bar</p>

Но поскольку простое регулярное выражение ищет только <, оно останавливается на <b> и выплевывает:

<p>foo </p><b>bold</b><p>bar</p> <!-- oops -->

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

(И перед неизбежным комментарием «Вы не можете разобрать HTML с регулярными выражениями!» Ввод не случайный HTML, а простой текст, снабженный только тегами <p>, <a>, <b> и <i> и / b / i не может быть вложенным.)

1 Ответ

3 голосов
/ 15 июня 2011

Я думаю, что вы на самом деле хотите положительный взгляд вперед. Это действительно неплохо:

/^([^<]+)(?=<p)/

Вы просто хотите убедиться, что все, что идет после <, равно p, но вы на самом деле не хотите потреблять <p, поэтому вы используете опережающее внимание.

Примеры:

> var re = /^([^<]+)(?=<p)/g;

> 'foo<p>bar</p>'.replace(re, '<p>$1</p>');
  "<p>foo</p><p>bar</p>"

> 'foo <b>bold</b><p>bar</p>'.replace(re, '<p>$1</p>')
  "foo <b>bold</b><p>bar</p>"

Извините, в моей первоначальной публикации было недостаточно ясно: я ожидал, что бит "foo bold" также будет заключен в новый тег p, но этого не происходит.

Кроме того, время от времени есть ввод без тегов p (просто foo), и он также должен отображаться на <p>foo</p>.

Самый простой способ, который я нашел, чтобы получить эту работу, это использовать 2 отдельных регулярных выражения, /^(.+?(?=<p))/ и /^([^<]+)/.

> var re1 = /^(.+?(?=<p))/g,
      re2 = /^([^<]+)/g,
      s = '<p>$1</p>';

> 'foo<p>bar</p>'.replace(re1, s).replace(re2, s);
  "<p>foo</p><p>bar</p>"

> 'foo'.replace(re1, s).replace(re2, s);
  "<p>foo</p>"

> 'foo <b>bold</b><p>bar</p>'.replace(re1, s).replace(re2, s);
  "<p>foo <b>bold</b></p><p>bar</p>"

Можно написать одно эквивалентное регулярное выражение, комбинируя re1 и re2:
/^(.+?(?=<p)|[^<]+)/

> var re3 = /^(.+?(?=<p)|[^<]+)/g,
      s = '<p>$1</p>';

> 'foo<p>bar</p>'.replace(re3, s)
  "<p>foo</p><p>bar</p>"

> 'foo'.replace(re3, s)
  "<p>foo</p>"

> 'foo <b>bold</b><p>bar</p>'.replace(re3, s)
  "<p>foo <b>bold</b></p><p>bar</p>"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...