这个group()如何捕获文本?

时间:2019-01-30 03:03:18

标签: java regex

我遇到了这个Hackerrank问题,正则表达式应该匹配HTML标记之间的字符串。正则表达式和字符串是

String str="<h1>Hello World!</h1>";
String regex="<(.+)>([^<]+)</\\1>";

如果'str'具有多个String str="<h1><h1>Hello World!</h1></h1>"这样的HTML标签,以及([^<]+)如何捕获此'str'怎么办。

我的问题是([^<]+)与'str'而不是([a-zA-Z]+)匹配。

这里是完整的源代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/* Solution assumes we can't have the symbol "<" as text between tags */
public class Solution{
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int testCases = Integer.parseInt(scan.nextLine());

        while (testCases-- > 0) {
            String line = scan.nextLine();

            boolean matchFound = false;
            Pattern r = Pattern.compile(regex);
            Matcher m = r.matcher(line);

            while (m.find()) {
                System.out.println(m.group(2));
                matchFound = true;
            }
            if ( ! matchFound) {
                System.out.println("None");
            }
        }
    }
}

别介意我是否愚蠢地问这个问题并预先感谢您!

2 个答案:

答案 0 :(得分:2)

如果输入字符串为Hello World!,则由于感叹号(!)和空格字符,([a-zA-z]+)将无法正确匹配。

更清楚地说,这是每个正则表达式的含义:

  • ([a-zA-Z]+)匹配由字母(大写或小写)组成的序列(1个或更多字符)

  • ([^<]+)匹配一个序列(1个或多个字符),只要一个字符不是一个<字符

答案 1 :(得分:2)

此正则表达式保证您的字符串仅包含一个标签,并假设HTML输入格式正确。

首字母<(.+)>捕获标签的名称。捕获组还将获得它可以获取的所有属性。由于+是贪婪的量词,因此它会捕获多个标签。

结尾的</\\1>与第一个捕获的匹配。这就是为什么如果您的HTML格式正确,则该表达式将无法捕获多个标签或具有以下属性的标签:

  • 开始标签<h1>,结束标签</h1>
  • 打开标签<h1 attr="value">,关闭标签</h1>,但期望</h1 attr="value">
  • 打开标签<h1><h2>,关闭标签</h2></h1>,但期望</h1><h2>

这就是为什么标签可以与.+相当安全地匹配的原因,而内容必须与[^<]+匹配。您想确保您没有抓住内容中的任何停留标签,但完全不允许使用其他任何字符。 [^<]+(读音。“至少不是<一次)允许使用!之类的东西,而[A-za-z]肯定不允许。