7.5.2 使用正则表达式

7.5.2 使用正则表达式

一旦在程序中定义了正则表达式,就可以使用PatternMatcher来使用正则表达式。
Pattern对象是正则表达式编译后在内存中的表示形式,因此,

  • 正则表达式字符串必须先被编译为Pattern对象,
  • 然后再利用该Pattern对象创建对应的Matcher对象。

执行匹配所涉及的状态保留在Matcher对象中,多个Matcher对象可共享同一个Pattern对象。

因此,典型的调用顺序如下:

1
2
3
4
5
//将一个字符串编译成Pattern对象
Pattern p= Pattern.compile("a*b");
//使用 Pattern对象创建 Matcher对象
Matcher m=p.matcher(\"aaaaab\");
boolean b=m.matches();//返回true

定义好的的Pattern对象可以多次重复使用。

直接使用Pattern类的静态matches方法

如果某个正则表达式仅需一次使用,则可直接使用Pattern类的静态matches方法,此方法自动把指定字符串编译成匿名的Pattern对象,并执行匹配。

1
boolean b= Pattern matches("a*b","aaaaab");//true

采用这种语句每次都需要重新编译新的Pattern对象,不能重复利用已编译的Pattern对象,所以效率不高.

Pattern类线程安全

Pattern是不可变类,可供多个并发线程安全使用。

Matcher类常用方法

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

CharSequence接口

PatternMatcher类的介绍中经常会看到一个CharSequence接口,该接口代表一个字符序列,其中CharBufferStringStringBufferStringBuilder都是它的实现类。简单地说, CharSequence代表一个各种表示形式的字符串。

通过Matcher类的find()group()方法可以从目标字符串中依次取出特定子串,例如互联网的网络爬虫,它们可以自动从网页中识别出所有的电话号码。

实例

下面程序示范了如何从大段的字符串中找出电话号码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.regex.*;

public class FindGroup {
public static void main(String[] args) {
// 使用字符串模拟从网络上得到的网页源码
String str = "卖豆腐:13500006666" + "交朋友:13611125565" + "出售二手电脑:15899903312";
// 创建一个Pattern对象,并用它建立一个Matcher对象
// 该正则表达式只抓取13X和15X段的手机号,
// 实际要抓取哪些电话号码,只要修改正则表达式即可。
Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str);
// 将所有符合正则表达式的子串(电话号码)全部输出
while (m.find()) {
System.out.println(m.group());
}
}
}

运行结果:

1
2
3
13500006666
13611125565
15899903312

find方法

find()方法依次查找字符串中与Pattern匹配的子串,一旦找到对应的子串,下次调用find()方法时将接着向下查找。
find()方法还可以传入一个int类型的参数,带int参数的find()方法将从该int索引处向下搜索.

开发一个简单网络爬虫的思路

使用正则表达式可以提取网页上的电话号码,也可以提取邮件地址等信息。如果程序再进一步,可以从网页上提取超链接信息,再根据超链接打开其他网页,然后在其他网页上重复这个过程就可以实现简单的网络爬虫了。

start()end()方法主要用于确定子串在目标字符串中的位置.

matches和lookingAt方法的区别

matches()lookingAt()方法有点相似,只是:

  • matches方法要求整个字符串和Pattern完全匹配时才返回true,
  • lookingAt()只要字符串以Pattern开头就会返回true

reset方法

reset()方法可将现有的Matcher对象应用于新的字符序列.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.regex.*;

public class MatchesTest
{
public static void main(String[] args)
{
String[] mails =
{
"kongyeeku@163.com" ,
"kongyeeku@gmail.com",
"ligang@crazyit.org",
"wawa@abc.xx"
};
String mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";
Pattern mailPattern = Pattern.compile(mailRegEx);
Matcher matcher = null;
for (String mail : mails)
{
if (matcher == null)
{
// 创建Matcher应用于第一个序列
matcher = mailPattern.matcher(mail);
}
else
{
// 匹配新的序列
matcher.reset(mail);
}
String result = mail + (matcher.matches() ? "是" : "不是")
+ "一个有效的邮件地址!";
System.out.println(result);
}
}
}

从某个角度来看, Matchermatches()lookingAt()String类的equals()startsWith()有点相似。区别是

  • String类的equals()startsWith()都是与字符串进行比较,
  • MatchermatcheslookingAt()则是与正则表达式进行匹配。

String类里也提供了matches方法,该方法返回该字符串是否匹配指定的正则表达式.

还可以利用正则表达式对目标字符串进行分割査找替换等操作.