Java中的正则表达式点运算符似乎总是很有效

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

我正在尝试从HTML片段中获取第一段内容。。。没什么比这更容易的了吧?但出于某种原因,
*?
操作符似乎工作贪婪:

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解析)。从我这里站起来。啊哈,我不是苏