34

假设我有以下字符串:

name1=gil;name2=orit;

我想找到所有匹配项name=value并确保整个字符串与模式匹配。

所以我做了以下事情:

  1. 确保整个模式与我想要的匹配。

    Pattern p = Pattern.compile("^((\\w+)=(\\w+);)*$");
    Matcher m = p.matcher(line);
    if (!m.matches()) {
        return false;
    }
    
  2. 迭代模式name=value

    Pattern p = Pattern.compile("(\\w+)=(\\w+);");
    Matcher m = p.matcher(line);
    while (m.find()) {
        map.put(m.group(1), m.group(2));
    }
    

有没有办法用一个正则表达式来做到这一点?

4

3 回答 3

39

您可以通过以下方式使用一个正则表达式验证和迭代匹配:

  • 通过在我们的正则表达式的开头name1=x;;name2=y;放置 a来确保匹配之间没有不匹配的字符(例如),这意味着“上一个匹配的结尾”\G

  • 通过将字符串的长度与 比较来检查我们是否在最后一次匹配中到达了字符串的末尾Matcher.end(),它返回最后一个匹配字符之后的偏移量。

就像是:

String line = "name1=gil;name2=orit;";
Pattern p = Pattern.compile("\\G(\\w+)=(\\w+);");
Matcher m = p.matcher(line);
int lastMatchPos = 0;
while (m.find()) {
   System.out.println(m.group(1));
   System.out.println(m.group(2));
   lastMatchPos = m.end();
}
if (lastMatchPos != line.length())
   System.out.println("Invalid string!");

现场演示

于 2013-05-29T15:03:26.030 回答
3

您必须为“^”和“$”启用多行模式才能按预期工作。

Pattern p = Pattern.compile("^(?:(\\w+)=(\\w+);)*$", Pattern.MULTILINE);
while (m.find()) {
    for (int i = 0; i < m.groupCount() - 2; i += 2) {
        map.put(m.group(i + 1), m.group(i + 2));
    }
}

正确的注释,您仍然必须遍历每行的匹配组,并使外部组成为非捕获组(?:...)

于 2013-05-29T14:52:16.410 回答
0
String example = "name1=gil;name2=orit;";
Pattern pattern = Pattern.compile("((name[0-9]+?=(.+?);))+?");
Matcher matcher = pattern.matcher(example);
// verifies full match
if (matcher.matches()) {
    System.out.println("Whole String matched: " + matcher.group());
    // resets matcher
    matcher.reset();
    // iterates over found
    while (matcher.find()) {
        System.out.println("\tFound: " + matcher.group(2));
        System.out.println("\t--> name is: " + matcher.group(3));
    }
}

输出:

Whole String matched: name1=gil;name2=orit;
    Found: name1=gil;
    --> name is: gil
    Found: name2=orit;
    --> name is: orit
于 2013-05-29T14:57:24.720 回答