Java 正则表达式


正则表达式是一种描述匹配模式的字符串。用来在一个字符串中查找、替换指定模式的子字符串。


元字符(Metacharacter)

元字符是有特殊含义的字符。元字符包含:<([{\^-=$!|]})?*+.>。除了元字符外的其它字符都匹配自己。

\字符是转义字符,会改变紧跟在它后面的字符的意义。如果要匹配元字符,需要在元字符前加上\

下面是元字符的例子:

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

public class MetaChar {
    public static void main(String[] args) {
        String regex = "ab.";
        String str = "ab2";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        if (matcher.matches())
            System.out.println("matched");    // matched
    }
}

上面例子中正则表达式ab.中的.是元字符,可以匹配任何字符。其它元字符的使用见后面的说明。


字符组(Character Class)

字符组是包含在中括号中的字符集合。字符组只匹配字符串中的一个字符。

字符组有下面几种:

  • 简单字符组,例如[abc],匹配a或b或c。
  • 否定(Negation)字符组,例如[^abc],除去a、b、c以外的所有其它字符。
  • 范围(Range)字符组,例如[a-cA-C],匹配a、b、c、A、B、C。[^a-c],除去a、b、c以外的所有其它字符。
  • 并集字符组,并集字符组包含2或多个字符组。例如[a-c[A-C]],匹配a、b、c、A、B、C。
  • 交集字符组,例如[a-g&&[efg]],匹配a、b、c、d。
  • 差集字符组,[a-d&&[^bc]],匹配a、d。

预定义的字符组,常用字符组的简写形式。

预定义字符组有下面几种:

  • .,匹配任何字符(可能不包含换行符)。
  • \d,数字,即[0-9]。
  • \D,非数字,即[^0-9]。
  • \s,空白字符,即[ \t\n\x0B\f\r]。\x0B表示竖tab键。
  • \S,非空白字符,即[^\s]。
  • \w,单词字符,即[a-zA-Z_0-9]。
  • \W,非单词字符,即[^\w]。

下面是字符组的例子:

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

public class CharClass {
    public static void main(String[] args) {
        String regex = "ab[a-g]";
        String str = "abc2abd";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            System.out.format("find " + " \"%s\" start at " +
                    " %d and end at index %d.%n", matcher.group(),
                    matcher.start(), matcher.end());
                    // find  "abc" start at  0 and end at index 3.
                    // find  "abd" start at  4 and end at index 7.
        }
    }
}


量词(Quantifier)

量词用于指定匹配出现的次数。

有下面几种量词:

  • x?,匹配0个或1个x。
  • x*,匹配0或多个x。
  • x+,匹配1或多个x。
  • x{n},匹配n个x。
  • x{n,},匹配至少n个x。
  • x{n,m},匹配至少n个x,但不超过m个x。

使用量词时默认是贪婪(greedy)匹配,如果在量词后面再加上?则表示使用惰性(reluctant)匹配,如果在量词后面加上+则表示使用支配(possessive)匹配。

下面是量词的例子:

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

public class Quantifier {
    public static void main(String[] args) {
        String regex = ".*ab";
        String regex2 = ".*?ab";
        String regex3 = ".*+ab";
        String str = "abc2abd";
        match(regex, str);
            // regex : .*ab, str : abc2abd
            // find  "abc2ab" start at  0 and end at index 6.
        match(regex2, str);
            // regex : .*?ab, str : abc2abd
            // find  "ab" start at  0 and end at index 2.
            // find  "c2ab" start at  2 and end at index 6.
        match(regex3, str);
            // regex : .*+ab, str : abc2abd 
    }

    private static void match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        System.out.printf("regex : %s, str : %s %n", regex, str);
        while (matcher.find()) {
            System.out.format("\tfind " + " \"%s\" start at " +
                    " %d and end at index %d.%n", matcher.group(),
                    matcher.start(), matcher.end());
        }
    }
}


捕获组(Capturing Group)

捕获组将多个字符当做一个单元看待。在多个字符前后加上括号(...)创建一个捕获组。

匹配的捕获组可以在后面使用,称为反向引用(backreference)。捕获组从左到右被编号。捕获组0表示整个字符串。反向引用使用\后跟捕获组编号来引用捕获组的值,例如\1

下面是捕获组的例子:

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

public class CaptureGroup {
    public static void main(String[] args) {
        String regex = "(ab)(cd)+e";
        String str = "abcde2abcdcde";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            System.out.format("find \"%s\" start at " +
                    " %d and end at index %d. group(1) : %s, group(2) : %s %n", matcher.group(),
                    matcher.start(), matcher.end(), matcher.group(1), matcher.group(2));
                    // find "abcde" start at  0 and end at index 5. group(1) : ab, group(2) : cd
                    // find "abcdcde" start at  6 and end at index 13. group(1) : ab, group(2) : cd
        }

        String regex2 = "(cd)\\1";
        String str2 = "cdcd";
        Pattern pattern2 = Pattern.compile(regex2);
        Matcher matcher2 = pattern2.matcher(str2);
        if (matcher2.matches())
            System.out.println("\t match");    // match
    }
}

匹配边界(Boundary Matcher)

匹配边界指匹配开始和结束的位置。

有下面几种匹配边界:

  • ^,行的开始。
  • $,行的结束。
  • \b,单词边界。
  • \B,非单词边界。
  • \A,输入的开始位置。
  • \G,前一个匹配的结束位置。
  • \Z,输入的结束位置,如果有换行符,去掉换行符。
  • \z,输入的结束位置。

下面是匹配边界的例子:

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

public class Boundary2 {
    public static void main(String[] args) {
        String regex = "^ab$";
        String str = "ab ";
        String regex2 = "\blike\b";
        String str2 = "dog likes bone";
        String regex3 = "\\Gdog";
        String str3 = "dog dog";
        match(regex, str);
            // egex : ^ab$, str : ab
        match(regex2, str2);
            // regex : like, str : dog likes bone
        match(regex3, str3);
            // regex : \Gdog, str : dog dog
            // find  "dog" start at  0 and end at index 3.
    }

    private static void match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        System.out.printf("regex : %s, str : %s %n", regex, str);
        while (matcher.find()) {
            System.out.format("\tfind " + " \"%s\" start at " +
                    " %d and end at index %d.%n", matcher.group(),
                    matcher.start(), matcher.end());
        }
    }
}