我的输入有缺陷,看起来像这样......
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可能不会嵌套。)
答案 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>"
通过合并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>"