3

我的问题是我想<div> xxx </div>从 HTML 的任意页面中删除一个。

所以给了一个页面......

<div> foo <div> bar <div> xxx </div> foo </div> bar </div>

我想结束

<div> foo <div> bar  foo </div> bar </div>

我以为这样replaceFirst("<div.*?xxx.*?</div>", "")就可以了。我假设了魔法?会使比赛变得懒惰并留下最初的 div。但是它坚持从第一个 div 开始贪婪和匹配。

由于我花了一个小时才找到解决方案,因此我在下面发布我的答案以保存后续答案。

4

3 回答 3

1

我认为这可能是使用正则表达式完成此任务的更正确方法,假设您想要最后一个<div>

"<div>((?!<div>).)*?xxx((?!<div>).)*?</div>"

尽管我倾向于说,如果您使用这样的负面环顾四周,您可能会更好地找到更适合该任务的工具。这是学术,真的。也许很有趣。但是,如果您从提供的示例中稍微提高复杂性,那么这个以及任何提供的解决方案都不会做得很好。

关于它们的更多信息,这里有一个关于它们的奇妙答案: 正则表达式匹配不包含单词的行?

于 2012-10-09T20:45:20.167 回答
0

我想出的答案是

.replaceFirst("<div[^(div)]*?xxx.*?</div>", ""); // WARNING - THIS IS BROKEN !!!

如果有更好的解决方案,我很乐意支持它。我仍然不明白为什么我的原始版本不起作用,但一切都很好,结果很好。

编辑:正如许多人指出的那样,当内部 div 包含 di 或 v 时,上述解决方案不起作用。

我结束了

.replaceFirst("(?s)(<div.*)<div.*xxx.*?</div>","$1");

共识是正则表达式和 HTML 就像卷心菜和奶油冻。虽然我确信这是个好建议,但我的具体情况是(a)我可以控制所有的 HTML,并且(b)我不能引入外部库。考虑到这些具体的考虑,我很满意正则表达式对我有用。

我希望后面的人会发现这个线程很有用,并感谢所有的贡献。

于 2012-10-09T19:39:50.790 回答
0

贪婪的匹配并不完全符合您的预期。它将尝试使子字符串匹配尽可能短,但仍会从它看到的第一个实例开始匹配。您也不想成功[^(div)],根据Pattern 文档,它不会匹配任何字符d, i, v, (, or )

我赞同反对在 HTML 上使用正则表达式的建议;从字面上看,它的表现力不足以很好地解析 HTML。相反,使用 HTML 解析器和 XPath 查询。

如果您确定您的 DIV 没有孩子,您最接近的近似值是执行以下操作:

.replaceFirst("<div[^<]+?xxx.*?</div>")

...其中[^<]+?将阻止前半部分找到任何带有子标签的 DIV。

于 2012-10-09T19:52:25.757 回答