正则表达式是一个强大的字符串处理工具 ,可以对字符串进行查找、提取、分割、替换等操作 。 String类里也提供了如下几个特殊的方法 :
上面这些特殊的方法都依赖于 Java 提供的正则表达式支持,除此之外, Java 还提供了 Pattem 和Matcher 两个类专门用于提供正则表达式支持。
正则表达式就是一个用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串 。
在其他语言中,\\ 表示:想要在正则表达式中插入一个普通的(字面上的)反斜杠,不要给它任何特殊的意义。在 Java 中,\\ 表示:要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。 所以,在其他的语言中(如Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在 Java 的正则表达式中,两个 \ 代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \d,而表示一个普通的反斜杠是 \\。
正则表达式所支持的合法字符如表一所示 :
表一:正则表达式所支持的合法字符
正则表达式中有一些特殊字符,这些特殊字符在正则表达式中有其特殊的用途:
表二:正则表达式中的特殊字符
将上面多个字符拼起来 , 就可以创建一个正则表达式。例如:
" \u0041\\\\ " // 匹配 A \
" \u0061 \t " // 匹配 a <制表符〉
" \\?\\ [" // 匹配? [
上面的正则表达式依然只 能匹配单个字符,这是因为还未在正则表达式中使用"通配符","通配符"是可以匹配多个字符的特殊字符。正则表达式中 的"通配符"远远超出了普通通配符的功能,它被称为预定义字符:
表三:预定义字符
上面的 7 个预定义字符其 实很容易记忆: d 是 digit 的意思,代表数字; s 是 space的意思, 代表空白; W 是 word 的意思 , 代表单词 。 d 、 s 、 w 的大写形式恰好匹配与之相反的字符 。
有了上面的预定义字符后 ,接下来就可以创建更强大的正则表达式了。 例如:
c\\wt //可 以匹配 cat 、 cbt 、 cct 、 cOt 、 c9t 等一批字符串
\\d\\d\\d-\\d\\d\\d-\d\\d\\d\\d //匹配如 000-000-0000 形式的电话号码
只想匹配 a~ f 的字母 ,或者匹配除 ab 之外的所有小写字母,或者匹配中文字符,此时就需要使用方括号表达式:
表四:方括号表达式
正则表示还支持圆括号表达式,用于将多个表达式组成一个子表达式 ,圆括号中可 以使用或运算符(|)。 例如, 正 则 表达式 "((public)|(Protected)l(private))"用于匹配 Java 的 三个访问控制符其中之 一。
Java 正则表达式还支持边界匹配符 :
表五:边界匹配符
前面例子中需要建立一个匹配 000-000-0000 形式的电话号码时,使用了\\d\d\d-\d\d\d-\d\d\d\d 正则表达式,这看起来比较烦琐 。 实际上,正则表达式还提供了数量标识符,正则表达式支持的数量标识符有如下几种模式 :
三种模式的数量表示符如表六所示 。
表六:三种模式的数量表示符
一旦在程序中定义了正则表达式,就可以使用 Pattem 和 Matcher 来使用正则表达式 。
Pattem 对象是正则表达式编译后在内存中的表示形式,因此,正则表达式宇符串必须先被编译为Pattem 对象,然后再利用该 Pattem 对象创建对应的 Matcher 对象 。 执行匹配所涉及的状态保留在 Matcher对象中,多个 Matcher 对象可共享同一个 Pattem 对象 。
因此,典型的调用顺序如下:
/ /将一个字符串编译成 Pattern 对象
Pattern p = Pattern.compil e( "a*b");
// 使用 Pattern 对象创建 Matcher 对象
Matcher m = p .matcher( "aaaaab" ) ;
boolean b = m.matches(); / /返回 true
上面定义的 Pattem 对象可以多次重复使用 。 如果某个正则表达式仅需一次使用,则可直接使用Pattem 类的静态 matches()方法,此方法自动把指定字符串编译成匿名的 Pattem 对象,并执行匹配,如下所示 :
boolean b = Pattern.matches("a*b" , "aaaaab"); // 返回 true
Pattem 是不可变类,可供多个并发线程安全使用 。
Matcher 类提供了如下几个常用方法 :
通过 Matcher 类的 findO和 groupO方法可以从目标字符串中依次取出特定子串(匹配正则表达式的子串),例如互联网的网络爬虫,它们可以自动从网页中识别出所有的电话号码 。 下面程序示范了如何从大段的宇符串中找出电话号码 :
FindGroup.java
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());
}
}
}
运行结果:
find()方法依次查找字符串中与 Pattem 匹配的子串, 一旦找到对应的子 串,下次调用 find()方法时将接着向下查找。
find()方法还可以传入一个 int 类型的参数,带 int 参数的 find()方法将从该 int 索引处向下搜索 。start()和 end()方法主要用于确定子串在目标字符串中的位置,如下程序所示:
StartEnd.java
public class StartEnd
{
public static void main(String[] args)
{
// 创建一个Pattern对象,并用它建立一个Matcher对象
String regStr = "Java is very easy!";
System.out.println("目标字符串是:" + regStr);
Matcher m = Pattern.compile("\\w+")
.matcher(regStr);
while(m.find())
{
System.out.println(m.group() + "子串的起始位置:"
+ m.start() + ",其结束位置:" + m.end());
}
}
}
运行结果:
matchesO和 lookingAt()方法有点相 似,只 是 matches()方法要求整个字符串和 Pattem 完全匹配时才返回 true ,而 lookingAtO只要字符串以 Pattem 开头就会返回 true 。 reset()方法可将现有的 Matcher 对象应用于新的字符序列 。看如下程序:
MatchesTest.java
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 = mailPattern.matcher(mail);
}
else
{
matcher.reset(mail);
}
String result = mail + (matcher.matches() ? "是" : "不是")
+ "一个有效的邮件地址!";
System.out.println(result);
}
}
}
运行结果:
除此之外 ,还可以利用正则表达式对目标字符串进行分割、查找、替换等操作,看如下程序:
ReplaceTest.java
public class ReplaceTest
{
public static void main(String[] args)
{
String[] msgs =
{
"Java has regular expressions in 1.4",
"regular expressions now expressing in Java",
"Java represses oracular expressions"
};
Pattern p = Pattern.compile("re\\w*");
Matcher matcher = null;
for (int i = 0 ; i < msgs.length ; i++)
{
if (matcher == null)
{
matcher = p.matcher(msgs[i]);
}
else
{
matcher.reset(msgs[i]);
}
System.out.println(matcher.replaceAll("哈哈:)"));
}
}
}
运行结果:
参考:
【1】:《疯狂Java讲义》 【2】:Java正则表达式 【3】:正则表达式匹配规则 【3】:正则表达式复杂匹配规则 【4】:正则表达式教程