java 正则表达式获取大括号之间的内容

先说下组的概念:java

捕获组

捕获组是把多个字符当一个单独单元进行处理的方法,它经过对括号内的字符分组来建立。正则表达式

例如,正则表达式 (dog) 建立了单一分组,组里包含"d","o",和"g"。spa

捕获组是经过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:翻译

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

能够经过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。code

还有一个特殊的组(group(0)),它老是表明整个表达式。该组不包括在 groupCount 的返回值中。对象

Java正则表达式匹配模式[贪婪型、勉强型、占有型],默认状况是贪婪模式匹配

贪婪模式表达式:three

表达式 含义
X? X,一次或一次也没有
X* X,零次或屡次
X+ X,一次或屡次
X{n} X,刚好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,可是不超过 m 次

非贪婪模式表达式:文档

表达式 含义
X?? X,一次或一次也没有
X*? X,零次或屡次
X+? X,一次或屡次
X{n}? X,刚好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,可是不超过 m 次

对于这三种匹配模式也有叫: “最大匹配Greedy”“最小匹配Reluctant”“彻底匹配Possessive”。如今将我对这三种匹配模式的理解写出来,并提供一些例子供你们参考。字符串

一、Greediness(贪婪型): 最大匹配table

X?、X*、X+、X{n,}都是最大匹配。例如你要用“<.+>”去匹配“a<tr>aava </tr>abb”,也许你所期待的结果是想匹配“<tr>”,可是实际结果却会匹配到“<tr>aava </tr>”。这是为何呢?下面咱们跟踪下最大匹配的匹配过程。

①“<”匹配字符串的“<”。

②“.+”匹配字符串的“<tr>aava </tr>ab”,在进行最大匹配时,它把两个“>”都匹配了,它匹配了全部字符,直到文本的最后字符“b”

③这时,发现不能成功匹配“>”,开始按原路回退,用“a”与“>”匹配,直到“ab”前面的“>”匹配成功。

这就是最大匹配,咱们匹配的时候应该看最后面能匹配到哪。

代码示例:
String test = "a<tr>aava </tr>abb ";
String reg = "<.+>";
System.out.println(test.replaceAll(reg, "###"));
输出:

a###abb

二、Reluctant(Laziness)(勉强型):最小匹配

X?、X*、X+、X{n,}都是最大匹配。好,加个?就成了Laziness匹配。例如X??、X*?、X+?、X{n,}?都是最小匹配,其实X{n,m}?和X{n }?有些多余。

最小匹配意味者,.+? 匹配一个字符后,立刻试一试>的匹配可能,失败了,则.+? 再匹配一个字符,再立刻试一试>的匹配可能。JDK文档中Greedy 和 Reluctant,它是以eat一口来隐喻的,因此翻译成贪吃和(勉强的)厌食最贴切了。不过我喜欢最大匹配、最小匹配的说法。

代码示例:
String test = "a<tr>aava </tr>abb ";
String reg = "<.+?>";
System.out.println(test.replaceAll(reg, "###"));
输出:
a###aava ###abb
和上面的不一样是匹配了两处。

三、Possessive(占有型):彻底匹配

与最大匹配不一样,还有一种匹配形式:X?+、X*+、X++、X{n,}+等,成为彻底匹配。它和最大匹配同样,一直匹配全部的字符,直到文本的最后,但它不禁原路返回。也就是说,一口匹配,搞不定就算了,到也干脆,偶喜欢。

代码示例:
String test = "a<tr>aava </tr>abb ";
String test2 = "<tr>";
String reg = "<.++>";
String reg2 = "<tr>";
System.out.println(test.replaceAll(reg, "###"));
System.out.println(test2.replaceAll(reg2, "###"));
输出:
a<tr>aava </tr>abb
###

可见。彻底匹配是最严格的,必须整个字符串匹配才行。

实例: 获取下面字符串中的大括号中的内容:

{one}{two}{three}

能够这样:

String s  = "{one}{two}{three}";
//由于默认为贪婪模式,因此若是没有使用显示()组中的元素不能为大括号([^}]*),而是使用(.*),
//那么会匹配的字符串为:one}{two}{three
Pattern p = Pattern.compile("\\{([^}]*)\\}");
Matcher m = p.matcher(s);
while (m.find()) {
  System.out.println(m.group(1));//第一次匹配成功是one,第二次匹配成功是two,第三次匹配为three
}

输出

one
two
three

若是想要三个大括号中的 内容一块儿输出,能够这样:

String s  = "{one}{two}{three}";
Pattern p = Pattern.compile("\\{([^}]*)\\}\\{([^}]*)\\}\\{([^}]*)\\}");
Matcher m = p.matcher(s);
while (m.find()) {
  System.out.println(m.group(1) + ", " + m.group(2) + ", " + m.group(3));//获取该次匹配中组(),正则表达式中只有一个(),即只分了一个组
}

输出

one, two, three

关于组的实例:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    public static void main( String args[] ){
 
      // 按指定模式在字符串查找
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(\\D*)(\\d+)(.*)";
 
      // 建立 Pattern 对象
      Pattern r = Pattern.compile(pattern);
 
      // 如今建立 matcher 对象
      Matcher m = r.matcher(line);
      if (m.find( )) {
         //每次匹配成功以后,表示利用pattern 获取到了匹配的字符串,而pattern 中有三个小括号,即有三个
         //组,那么每次匹配成功确定有group(1),group(2),group(3),group(0)是它老是表明整个表达式
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
         System.out.println("Found value: " + m.group(3) ); 
      } else {
         System.out.println("NO MATCH");
      }
   }
}

运行结果以下:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?
相关文章
相关标签/搜索