优化Regex以在两个标签之间提取内容(或如何使用Jsoup选择器API在两个标签之间选择内容?)

时间:2014-02-02 13:48:19

标签: java html regex

我正在尝试创建一个正则表达式来从我们的doc站点中提取两个锚标记之间的内容。

我们以JDK wiki page为例。我想在“JDK内容”和“JDK和SDK之间的歧义”之间提取内容。我目前的正则表达式是:

<span[^>]*\bid\s*=\s*(?:"|')?JDK_contents(?:'|")?[^>]*>([^<]*)</span>(.*?)
(<span[^>]*\bid\s*=\s*(?:"|')?Ambiguity_between_a_JDK_and_an_SDK(?:'|")?[^>]*>[^<]*</span>.*)

但是由于这种正则表达式会被执行多次,我想优化它。

我可以考虑的一件事是.*?: </span>(.*?)(<span[^>]...) 因为它会匹配任何东西,并导致大量的回溯。

顺便说一句,我也尝试了贪婪的版本:</span>(.*)(<span[^>]...),但由于.*匹配所有文字,然后回溯到Ambiguity_between_a_JDK_and_an_SDK范围,它会慢得多。

我正在使用Java。任何人都可以帮忙提供一些见解吗?

1 个答案:

答案 0 :(得分:0)

您可以使用Jsoup的css选择器实现相同的效果。

<强>解

h2:has(span#JDK_contents) ~ *:not(h2:has(span#Ambiguity_between_a_JDK_and_an_SDK) ~ *):not(h2)

DEMO

<强>描述

为清楚起见,让我们调用h2Start一个至少有一个带有 JDK_contents 的跨度的h2标签。我们也会调用h2End一个至少有一个带有 Ambiguity_between_a_JDK_and_an_SDK 的跨度的h2代码。

h2:has(span#JDK_contents)  /* Select an h2Start */
~ *                        /* Select any node preceded by this h2Start... */
:not(h2:has(span#Ambiguity_between_a_JDK_and_an_SDK) ~ *) /* ...but not peceded by an h2End */
:not(h2) /* We remove h2End  */

<强> NOTA: JDK wiki page的情况下,最后一行就足够了。更严格的是,我们会将其替换为:not(h2:has(span#Ambiguity_between_a_JDK_and_an_SDK))