Java中正则表达式

正则表达式是一个用于匹配的模板,可以对字符串进行查找、提取、分割、替换等操作。String 类里也提供了几个特殊的方法:

  • boolean matches(String regex):判断字符串是否匹配指定的正则表达式。
  • String replaceAll(String regex,String replacement):将字符串中所有匹配 regex 的子串替换成 replacement。
  • String replaceFirst(String regex,String replacement):将字符串中第一个匹配 regex 的子串替换成 replacement。
  • String[] split(String regex):以 regex 作为分隔符,把该字符串分割成多个子串

除此之外,Java还提供了 PatternMatcher 两个类专门用于提供正则表达式支持。

创建正则表达式

前面介绍,正则表达式就是一个用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串。


除此之外,正则表达式中有一些特殊字符,这些特殊字符在正则表达式中有特殊的用途,比如反斜线(\)。如果需要匹配这些特殊字符,就必须首先将这些字符转义。

正则表达式中还能使用通配符,通配符可以匹配多个字符,又称为预定义字符。

提示:ddigit 的意思,代表数字;sspace 的意思,代表空白;wword 的意思,代表单词;d、s、w 的大写形式切好匹配与之相反的字符。

特殊情况下还能使用方括号表达式:

正则表达式还支持圆括号表达式,用于将多个表达式组成一个子表达式,圆括号中可以使用 或运算符 (|)。例如,正则表达式 ((public)|(protected)|(private)) 用于匹配Java的三个访问控制符其中之一。

除此之外,Java正则表达式还支持几个边界匹配符:

当需要建立一个匹配 000-0000-0000 形式的电话号码时,使用了 \\d\\d\\d-\\d\\d\\d\\d-\\d\\d\\d\\d 正则表达式,这看起来比较繁琐。实际上,正则表达式还提供了数量标识符,正则表达式支持的数量标识符有如下几种模式:

  • Greedy(贪婪模式):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的正则表达式会一直匹配下去,直到无法匹配为止。
  • Reluctant(勉强模式):用问号后缀 (?) 表示,它只会匹配最少的字符,也称为最小匹配模式。
  • Prossesive(占有模式):用加号后缀(+)表示,目前只有Java支持占有模式,通常比较少用。

三种模式的数量表示符如下:

使用正则表达式

一旦在程序中定义了正则表达式,就可以使用 PatternMatcher 来使用正则表达式。

Pattern 对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为 Pattern 对象,然后再利用该 Pattern 对象创建对应的 Matcher 对象。执行匹配所涉及的状态保留在 Matcher 对象中,多个 Matcher 对象可共享同一个 Pattern 对象。

1
2
3
4
5
//将一个字符串正则表达式编译成 Pattern 对象
Pattern pattern=Pattern.compile("a*b");//a*b 为正则表达式
//使用 Pattern 对象创建 Matcher 对象
Matcher matcher= pattern.matcher("aaaaab");//aaaaab 为需要查找的文本字符串
boolean b=m.matches();//返回 true

Matcher 类提供了如下几个常用的方法:

  • find():返回目标字符串中是否包含与 Pattern 匹配的子串。
  • group():返回上一次与 Pattern 匹配的子串。
  • start():返回上一次与 Pattern 匹配的子串在目标字符串中的开始位置。
  • end():返回上一次与 Pattern 匹配的子串在目标字符串中的结束位置加1。
  • lookingAt():返回目标字符串前面部分与 Pattern 是否匹配。
  • matches():返回整个目标字符串与 Pattern 是否匹配。
  • reset():将现有的 Matcher 对象应用于一个新的字符序列。

通过 Matcher 类的 find() 和 group() 方法可以从目标字符串中依次取出特定子串(匹配正则表达式的子串),例如网络爬虫,可以自动从网页中识别出所有的电话号码。

1
2
3
4
5
6
7
8
9
10
11
//使用字符串模拟从网络上得到的网页源码
String str = "我想求购一本《疯狂 Java 讲义》,尽快联系我 13500006666" + "交朋友,电话号码是 13611125565" + "出售二手电脑,联系方式是 15899903312";
//创建一个 Pattern 对象,并用它建立一个 Matcher 对象
//该正则表达只抓取 13X 和 15X 段的手机号
//实际要抓取哪些电话号码,只要修改正则表达式即可
Matcher matcher = Pattern.compile("((13\\d) | (15\\d)) \\d{8}").matcher(str);
//将所有符号正则表达式的子串(电话号码)全部输出
while(matcher.find())
{
System.out.println(matcher.group());
}