Skip to content

Java正则多次匹配和多次组匹配

关于正则表达式 , 可以学习下这篇介绍 : 正则表达式

替换

单文的多次匹配

有以下几种方式 , 把a全匹配替换

替换 a

java
"aab".replaceAll("a{1}", "x"); //xxb
"aba".replaceAll("a{1}", "x"); //xbx
"aab".replaceAll("a{1}", "x"); //xxb
"aba".replaceAll("a{1}", "x"); //xbx

替换 aa

java
"abaaabaaaba".replaceAll("a{2}", "x");  //abxabxaba
"abaabaaaaba".replaceAll("a{2}", "x"); //abxbxxba
"abaaabaaaba".replaceAll("a{2}", "x");  //abxabxaba
"abaabaaaaba".replaceAll("a{2}", "x"); //abxbxxba

重要

replaceAll()方法会将所有匹配到的全部替换掉.

提取

提取就需要用到group

提取 a

java
Matcher matcher = Pattern.compile("(a)").matcher("ab");
if(matcher.find()){
    System.out.println(matcher.group());
}

// 结果
a
Matcher matcher = Pattern.compile("(a)").matcher("ab");
if(matcher.find()){
    System.out.println(matcher.group());
}

// 结果
a

提取多个 a

group只有提取一次匹配到的 , 要多次提取 , 需要循环匹配.

java
Matcher matcher = Pattern.compile("(a)").matcher("aba");
int matcher_start = 0;
while (matcher.find(matcher_start)){
    System.out.println(matcher.group(1));
    matcher_start = matcher.end();
}

// 结果
a
a
Matcher matcher = Pattern.compile("(a)").matcher("aba");
int matcher_start = 0;
while (matcher.find(matcher_start)){
    System.out.println(matcher.group(1));
    matcher_start = matcher.end();
}

// 结果
a
a

提取复杂内容

示例在一个文本中提取多个xml标签

java
String txt = "abc123<root>这是root1</root><root>这是root2</root>";
Matcher matcher = Pattern.compile("<root>(.*?)</root>").matcher(txt);
int matcher_start = 0;
while (matcher.find(matcher_start)){
    System.out.println(matcher.group(1));
    matcher_start = matcher.end();
}

// 结果
这是root1
这是root2
String txt = "abc123<root>这是root1</root><root>这是root2</root>";
Matcher matcher = Pattern.compile("<root>(.*?)</root>").matcher(txt);
int matcher_start = 0;
while (matcher.find(matcher_start)){
    System.out.println(matcher.group(1));
    matcher_start = matcher.end();
}

// 结果
这是root1
这是root2

group使用的注意点

多匹配和少匹配

上面的复杂示例中, 正则是 <root>(.*?)</root> , 中间的分组匹配是 (.*?) ,里面是有个问号?的 .

正则默认是多匹配的, 尽可能多的匹配到文本.

  • 多匹配

那么不加?时, 只能匹配到一个文本 , <root>(.*)</root> 匹配到的是: 这是root1</root><root>这是root2 , 会把中间的全部匹配进去了. 这就是多匹配

  • 少匹配

要尽可能少的匹配 , 就需要加上?,<root>(.*?)</root> 匹配到的是: 这是root1. 这个结果一般才是想要的.

group 匹配的组的顺序

java
matcher.group(1) // 这里是group序号1
matcher.group(1) // 这里是group序号1

group匹配后得到是一个数组 , 数组0位置是全匹配文本 , 数组1位置才是第一个匹配到的分组.

例如:

上面的示例中, <root>(.*?)</root>得到的group(0) 是 <root>这是root1</root> .

序号不好识别的话, 可以用别名来识别 .

java
//String txt = "abc123<root>这是root1</root><root>这是root2</root>";
  //Matcher matcher = Pattern.compile("<root>(?<element>.*?)</root>").matcher(txt);
  int matcher_start = 0;
  while (matcher.find(matcher_start)){
      System.out.println(matcher.group("element"));
      matcher_start = matcher.end();
  }

// 结果
这是root1
这是root2
//String txt = "abc123<root>这是root1</root><root>这是root2</root>";
  //Matcher matcher = Pattern.compile("<root>(?<element>.*?)</root>").matcher(txt);
  int matcher_start = 0;
  while (matcher.find(matcher_start)){
      System.out.println(matcher.group("element"));
      matcher_start = matcher.end();
  }

// 结果
这是root1
这是root2

element就是文本的别称 , 可以直接用别称提取内容.