我目前正在尝试使用RegEx解析Java中的一些HTML。在实时代码的较小测试样本上它可以工作,但是在对实时代码进行尝试时,正则表达式引擎会破坏堆栈。
以下是我正在使用的代码和RegEx。
/**
* RegEx Explanation:
* "(?i)" - Turn on case insensitive mode
* "<BR><BR><B>.+?</B><BR>" - Match the format for a group name
* "(?-i)" - Turn off case insensitive mode
* "(.|\\r|\\n)" - Match all the text following the group name incl. newlines
* "(?=((?i)<BR><BR><B>.+?</B><BR>(?-i))" - and lookahead for the start of a new group, make the match lazy and use case-insensitive mode
* "+?)" - Make the lookahead lazy, close out the capture group.
*/
Pattern filterPattern =
Pattern.compile("(?i)(<BR><BR><B>.+?</B><BR>)(?-i)(.|\\r|\\n)+?(?=((?i)<BR><BR><B>.+?</B><BR>(?-i))+?)");
Matcher match = filterPattern.matcher(content);
ArrayList<String> groups = new ArrayList<String>();
// Retrieve the matches found by the RegEx
while(match.find()) {
if(match.groupCount() > -1) {
groups.add(match.group(0));
}
}
实时html是一个电路板列表(http://menu.2ch.net/bbsmenu.html),但一般格式为:
<br><br><b>Group name</b><br>
<a href="board url">Name of the board</a><br>
使用不同数量的链接重复多次。我避免使用像JSoup这样的常规HTML解析器,因为格式是一致的,并且在第一遍中使用RegEx更容易定位以提取部分。
当我调用group()时发生堆栈溢出。其他问题表明这是由于Java中的group()调用没有对递归深度的限制,因此它将一直运行直到达到堆栈限制。我不太擅长RegEx,这可能就是为什么我错过了一个可能更容易表达的原因。我怀疑递归问题是在交替时发生的(。| \ r | \ n),但由于组太多,它可能很容易发生。我不知道。
是否有更好的表达方式来避免灾难性的复发?
答案 0 :(得分:2)
为了帮助您使用正则表达式,请考虑(这些都没有经过测试,仅来自内存):
(?is)(?:<BR><BR><B>(.+?)</B><BR>)(.*?)(?=<BR><BR><B>.+?</B><BR>)
或
(?i)(?:<BR><BR><B>(.+?)</B><BR>)\s*((?:<A HREF=.*?>.*?</A><BR>\s*)+)
((?i)blah(?-i))
很难阅读,请改用(?i:blah)
,这就是它的设计方式,或只使用一个(?i)
,因为您不希望任何特定的区分大小写正确的正则表达式DOTALL
模式,则可以撰写.*?
,并且它也会匹配"hello\n\r\tworld"
。(.|\\r|\\n)+?
和前瞻:你不需要重复下一个标题,你只是在寻找下一个的存在group(1)
和group(2)
分别查找标题和链接:(?:I'm not a numbered group)
。(.|\\r|\\n)+?
:<A HREF=(.*?)>(.*?)</A><br>\n
+?
,也许是(?=...)?
使其成为可选匹配,但我我不确定它会起作用。使用第二个选项,更重要的是!