我有一个正则表达式来从 HTML 源代码中提取 id 和标签。可以查到HERE .
正如你所看到的,它工作得很好而且速度很快,但是当我用相同的源代码在java中尝试这个正则表达式时,它1.永远使用并且2.只匹配一个字符串(从第一个a
到最后一个 a
是一个匹配)。
我尝试使用 Multiline
标志打开和关闭,但没有区别。我不明白正则表达式如何在除了java之外的任何地方工作。有什么想法吗?
private static final String COURSE_REGEX = "<a class=\"list-group-item list-group-item-action \" href=\"https:\\/\\/moodle-hs-ulm\\.de\\/course\\/view\\.php\\?id=([0-9]*)\"(?:.*\\s){7}<span class=\"media-body \">([^<]*)<\\/span>";
Pattern pattern = Pattern.compile(COURSE_REGEX, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(sourceCode);
List<String> courses = new ArrayList<>();
while(matcher.find() && matcher.groupCount() == 2){
courses.add(matcher.group(1) + "(" + matcher.group(2) + ")");
}
最佳答案
您的正则表达式遇到 catastrophic backtracking由于可能的排列数量庞大,子表达式 (?:.*\s){7}
需要检查(因为 .
也可以匹配空格)。 Java 在一定数量的步骤后中止匹配尝试(不确定有多少,当然> 1.000.000)。 PHP或者JS可能没那么谨慎。
如果您将正则表达式的该部分简化为 .*?
,您确实得到了匹配项:
"(?s)<a class=\"list-group-item list-group-item-action \" href=\"https://moodle-hs-ulm\\.de/course/view\\.php\\?id=([0-9]*)\".*?<span class=\"media-body \">([^<]*)</span>"
请注意,您需要 DOTALL
标志( (?s)
,因此 .
可能匹配换行符)而不是 MULTILINE
改变 ^
行为的标志和$
anchor (您的正则表达式没有使用这些 anchor )。
另请注意,您不需要在 Java 正则表达式中转义斜杠。
这个解决方案不是很稳健,因为 .*?
是相当不具体的。我想你之前尝试过 (?:.*\\s){7}
可能被设计为匹配不超过 7 行的文本?在这种情况下,您可以使用 (?:(?!</a>).)*
而是确保您不会进入下一个 <a>
标签。这是使用正则表达式解析 HTML 的危险之一:)
最后,来自贵校信息学系工作人员的问候:)
关于javascript - RegExp 适用于 JS 和 PHP,但不适用于 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54305864/