Java中的正则表达式点运算符似乎总是很有效
我正在尝试从HTML片段中获取第一段内容。。。没什么比这更容易的了吧?但出于某种原因,Java中的正则表达式点运算符似乎总是很有效,java,regex,Java,Regex,我正在尝试从HTML片段中获取第一段内容。。。没什么比这更容易的了吧?但出于某种原因,*?操作符似乎工作贪婪: import java.util.regex.Matcher; 导入java.util.regex.Pattern; 公开课考试 { 公共静态void main(字符串[]args) { Pattern regex=Pattern.compile(“]*)?>(.*?”,Pattern.DOTALL); Matcher match=regex.Matcher(“foobar”; Sys
*?
操作符似乎工作贪婪:
import java.util.regex.Matcher;
导入java.util.regex.Pattern;
公开课考试
{
公共静态void main(字符串[]args)
{
Pattern regex=Pattern.compile(“]*)?>(.*?”,Pattern.DOTALL);
Matcher match=regex.Matcher(“foo
bar”;
System.out.println(match.matches());
系统输出println(匹配组(1));
}
}
我希望只匹配第一段的内容(foo
),但结果如下:
$ javac test.java && java test
true
foo</p> <p>bar
$javac test.java&&java测试
符合事实的
foo酒吧
如npinti所解释的,*?
在第一次之后继续匹配的任何原因,都是调用匹配.match()
引起的问题。这将尝试将模式与整个输入字符串相匹配。只有当正则表达式引擎找到某种方式将字符串表示为模式的实例时,它才会成功。实现这一点的唯一方法是将(.*)
与foo条
匹配
有两种方法可以解决此问题:
最简单的方法是切换到match.find()
。这将在字符串中查找模式的第一个匹配项。由于不需要匹配整个字符串,因此非贪婪量词可确保根据需要获得foo
调整图案以匹配整个字符串。例如,“]*)?>(.*)*”
然而,不可避免地,这些“简单”的计划是解析一些HTML。用类似的东西解析HTML真的很简单。现在切换到那个,不要回头看。看看这有多容易:
Document doc = Jsoup.parseBodyFragment("<p class=\"baz\">foo</p> <p>bar</p>");
Elements paragraphs = doc.getElementsByTag("p");
if (paragraphs.size() > 0) {
System.out.println(paragraphs.get(0).text());
}
Document doc=Jsoup.parseBodyFragment(“foo
bar”;
元素段落=doc.getElementsByTag(“p”);
如果(段落.size()>0){
System.out.println(段落.get(0.text());
}
打印:foo
正如npinti所解释的,该问题是由调用match.match()
引起的。这将尝试将模式与整个输入字符串相匹配。只有当正则表达式引擎找到某种方式将字符串表示为模式的实例时,它才会成功。实现这一点的唯一方法是将(.*)
与foo条
匹配
有两种方法可以解决此问题:
最简单的方法是切换到match.find()
。这将在字符串中查找模式的第一个匹配项。由于不需要匹配整个字符串,因此非贪婪量词可确保根据需要获得foo
调整图案以匹配整个字符串。例如,“]*)?>(.*)*”
然而,不可避免地,这些“简单”的计划是解析一些HTML。用类似的东西解析HTML真的很简单。现在切换到那个,不要回头看。看看这有多容易:
Document doc = Jsoup.parseBodyFragment("<p class=\"baz\">foo</p> <p>bar</p>");
Elements paragraphs = doc.getElementsByTag("p");
if (paragraphs.size() > 0) {
System.out.println(paragraphs.get(0).text());
}
Document doc=Jsoup.parseBodyFragment(“foo
bar”;
元素段落=doc.getElementsByTag(“p”);
如果(段落.size()>0){
System.out.println(段落.get(0.text());
}
打印:foo
很抱歉没有在前面发布此内容,因为您没有访问Java环境的权限
问题是matches()
将尝试匹配整个字符串。这意味着它将隐式添加^
和$
。将matches()
替换为find()
可以解决此问题:
Pattern regex = Pattern.compile("<p(?: [^>]*)?>(.*?)</p>", Pattern.DOTALL);
Matcher match = regex.matcher("<p class=\"baz\">foo</p> <p>bar</p>");
System.out.println(match.find());
System.out.println(match.group(1));
很抱歉没有在前面发布此消息,因为您没有访问Java环境的权限
问题是matches()
将尝试匹配整个字符串。这意味着它将隐式添加^
和$
。将matches()
替换为find()
可以解决此问题:
Pattern regex = Pattern.compile("<p(?: [^>]*)?>(.*?)</p>", Pattern.DOTALL);
Matcher match = regex.matcher("<p class=\"baz\">foo</p> <p>bar</p>");
System.out.println(match.find());
System.out.println(match.group(1));
它在这里工作,尝试替换System.out.println(match.matches())代码>与System.out.println(match.find())匹配代码>强制注释:您是否考虑过使用DOM解析器来实现此目的?@Duncan:matches()
尝试匹配整个字符串find()
将找到第一个匹配项并从那里继续。点本身并不贪婪;它将始终匹配一个且仅匹配一个字符。你使用的量词可能贪婪,也可能不贪婪,甚至占有(*++
,++
等)。它在这里起作用,请尝试替换System.out.println(match.matches())代码>与System.out.println(match.find())匹配代码>强制注释:您是否考虑过使用DOM解析器来实现此目的?@Duncan:matches()
尝试匹配整个字符串find()
将找到第一个匹配项并从那里继续。点本身并不贪婪;它将始终匹配一个且仅匹配一个字符。你使用的量词可能贪婪,也可能不贪婪,甚至是占有欲(*++
,++
等等)。感谢你的所有提示,我们将调查JSoup,但现在只需使用find()
@RafałWrzeszcz>修复代码:按照建议坚持JSoup。将为您的未来节省很多麻烦。@RafałWrzeszcz我添加了一个JSoup示例。它比正则表达式简单得多…感谢您提供的所有提示,我们将调查JSoup,但现在我们只需使用find()
@RafałWrzeszcz修复代码:按照建议使用JSoup。将为您的未来节省很多麻烦。@RafałWrzeszcz我添加了一个JSoup示例。这比正则表达式简单得多…啊哈,我不确定你会给出答案。我会留下我的,因为它有一些更多的细节,但是请投我一票来解决这个问题@邓肯:你的答案更好,因为你推广了JSoup
(你应该如何处理HTML解析)。从我这里站起来。啊哈,我不是苏