Java正则表达式匹配器 - 多个组

时间:2015-03-22 23:15:08

标签: java regex

我正在使用Pattern和Matcher创建一个regexp,它将从我在下面的li标签中提取6个值:

 <ul class="Bold">                                <li class="ball-orange">2</li>                                <li class="ball-orange">10</li>                                <li class="ball-orange">11</li>                                <li class="ball-orange">15</li>                                <li class="ball-orange">22</li>                                <li class="ball-orange">39</li>                            </ul>

即。正则表达式的结果需要是2,10,11,15,22,39的组。

我有以下代码:

Pattern numbersPattern = Pattern.compile(".*(<li class=\"ball-orange\">([0-9]{1,2})</li>).*");
Matcher matchNumbers = numbersPattern.matcher(mainBlock);//mainBlock is the string I quoted above which contains all the li's
System.out.println("Numbers Match? " + matchNumbers.matches());//this returns true
System.out.println(matchNumbers.group(2));//returns 39, i.e. second group but for the last li

//this loop never gets entered!!!
while (matchNumbers.find()) {
    System.out.println("group 1: " + matcher.group(1));
    System.out.println("group 2: " + matcher.group(2));
    //System.out.println("group 3: " + matcher.group(3));
}

因此,您可以从评论中看到匹配最后一个li,但它不会进入while(matchNumbers.find())循环。即我希望找到(<li class=\"ball-orange\">([0-9]{1,2})</li>) 6次,并在循环中输出,但不是。

我跟随这里的啧啧 - http://tutorials.jenkov.com/java-regex/matcher.html#groups-inside-groups

为什么没有输入循环,怎样才能让li的组匹配?

3 个答案:

答案 0 :(得分:2)

您的正则表达式.*(<li class=\"ball-orange\">([0-9]{1,2})</li>).*将占用整个字符串,因为.*在开头和结尾。如果您想进入循环,请考虑仅使用(<li class=\"ball-orange\">([0-9]{1,2})</li>)部分。

甚至更好,而不是正则表达式使用适当的工具:HTML解析器,如jsoup:

String mainBlock = "<ul class=\"Bold\">                                <li class=\"ball-orange\">2</li>                                <li class=\"ball-orange\">10</li>                                <li class=\"ball-orange\">11</li>                                <li class=\"ball-orange\">15</li>                                <li class=\"ball-orange\">22</li>                                <li class=\"ball-orange\">39</li>                            </ul>";
Document doc = Jsoup.parse(mainBlock);
for (Element el : doc.select("li.ball-orange")){//pick all <li class="ball-orange"> tags
    System.out.println("li tag: " + el);
    System.out.println("value in li : " + el.text());
}

输出:

li tag: <li class="ball-orange">2</li>
value in li : 2
li tag: <li class="ball-orange">10</li>
value in li : 10
li tag: <li class="ball-orange">11</li>
value in li : 11
li tag: <li class="ball-orange">15</li>
value in li : 15
li tag: <li class="ball-orange">22</li>
value in li : 22
li tag: <li class="ball-orange">39</li>
value in li : 39

答案 1 :(得分:1)

目前,您热切地匹配整个字符串(任何内容+ li +任何内容),这就是matches() == true的原因。如果你想要所有,只需删除.*部分,因为.find()会多次找到你的模式,首先是位置~25,然后是〜60等等......:

    String mainBlock = "<ul class=\"Bold\">                                <li class=\"ball-orange\">2</li>                                <li class=\"ball-orange\">10</li>                                <li class=\"ball-orange\">11</li>                                <li class=\"ball-orange\">15</li>                                <li class=\"ball-orange\">22</li>                                <li class=\"ball-orange\">39</li>                            </ul>";
    Pattern listPattern = Pattern.compile("<li class=\"ball-orange\">([0-9]{1,2})</li>");
    Matcher matcher = listPattern.matcher(mainBlock);
    while (matcher.find()) {
        System.out.println("whole thing: " + matcher.group()); // or group(0)
        System.out.println("number: " + matcher.group(1));
    }
  

整件事:&lt; li class =&#34; ball-orange&#34;&gt; 2&lt; / li&gt;

  编号:2
  整件事:&lt; li class =&#34; ball-orange&#34;&gt; 10&lt; / li&gt;

  数量:10
  整件事:&lt; li class =&#34; ball-orange&#34;&gt; 11&lt; / li&gt;

  数量:11
  整件事:&lt; li class =&#34; ball-orange&#34;&gt; 15&lt; / li&gt;

  数量:15
  整件事:&lt; li class =&#34; ball-orange&#34;&gt; 22&lt; / li&gt;

  数量:22
  整件事:&lt; li class =&#34; ball-orange&#34;&gt; 39&lt; / li&gt;

  数量:39

注意:你永远不需要在整个正则表达式中放置一个组,根据定义捕获组0是整个匹配,这就是为什么编号从1开始。

答案 2 :(得分:-1)

您必须将正则表达式更改为"\<li class=\"ball-orange\"\>\d{1,2}\</li\>"使用\ d而不是[0-9]

Pattern numbersPattern = Pattern.compile("\<li class=\"ball-orange\"\>\d{1,2}\</li\>");
        Matcher matchNumbers = numbersPattern.matcher(mainBlock);//mainBlock is the string I quoted above which contains all the li's
        System.out.println("Numbers Match? " + matchNumbers.matches());//this returns true
        System.out.println(matchNumbers.group(2));//returns 39, i.e. second group but for the last li

        //this loop never gets entered!!!
        while (matchNumbers.find()) {
            System.out.println("group 1: " + matcher.group(1));
            System.out.println("group 2: " + matcher.group(2));
            //System.out.println("group 3: " + matcher.group(3));
        }