基本上我需要匹配不属于封闭 <p> 标记的 HTML 中的任何 / 。这是我到目前为止所得到的,但它并没有按预期工作,我已经尝试了一段时间。
((?<!(p))\/(?!(>))) | ((?<!(<))\/(?!(p)))
我还需要正则表达式才能在 Java 中工作。
举个例子:
<div>测试</div> <span>测试</span> <p>某事<p/> </p>
我希望它匹配/
除了最后<p>
标签中的之外的所有内容!
/(?!p)
这似乎有效。但我不确定问题是什么。
<div>test</div> <span>test</span> <p>something<p/> </p>
matches: / / /
幸运的是,Java 同时支持lookbehind 和lookahead(相比之下,我大部分时间都在使用的语言JavaScript 只支持lookahead)。
所以你正在寻找的模式是:
(?<!<p)/(?!p>)
此模式将匹配任何前面既不是 a<p
也不是后跟 a的斜杠p>
。因此它排除<p/>
以及</p>
。
前瞻/后瞻断言(通常称为“零宽度”断言)实际上并未包含在匹配中,这听起来像是您想要的。它基本上断言你试图匹配的东西前面是(lookbehind)或后面是(lookahead)一个子表达式。在这种情况下,我们使用否定断言(前面没有/后面没有)。
使用正则表达式解析 HTML 是一项棘手的工作。正如一个答案所指出的那样,HTML 是上下文无关的,因此不能完全被 HTML 解析,从而留下了 HTML 混淆匹配的可能性。我们甚至不要开始使用格式错误的 HTML。
不过,我会考虑以下对空标签的常见变体:
<p />
为了处理这个问题,我会在匹配中添加一些空格:
(?<!<p\s*)/(?!p>)
您可能会遇到问题的地方是奇怪的空格(仍然是有效的 HTML)。以下斜杠将与上述正则表达式匹配:
< p/>
<p/ >
这可以通过在您的正则表达式中添加更多的空格重复来解决。如前所述,这也将匹配文本中的斜线,因此以下输入将仅匹配一个斜线(文本中的那个):
<p>some text / other text</p>
最后,当然还有 CDATA 组。以下输入将匹配 NO 斜杠:
<![CDATA[This <p/> isn't actually a tag...it's just text.]]>