正则表达式匹配内容直到多字符串

时间:2011-06-15 03:15:13

标签: javascript regex html-parsing regex-negation

我的输入有缺陷,看起来像这样......

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?显然,答案涉及消极的前瞻,但this对我来说有点太深了。

(在不可避免的“你不能用正则表达式解析HTML!”注释之前,输入不是随机HTML,而是仅用标签<p><a>,{{注释的纯文本1}}和<b>,并且a / b / i可能不会嵌套。)

1 个答案:

答案 0 :(得分:3)

我认为你实际上想要积极前瞻。这真的不错:

/^([^<]+)(?=<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>"

通过合并re1re2,可以编写一个等效的正则表达式:
/^(.+?(?=<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>"
相关问题