正则表达式
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。String类里也提供了如下几个特殊的方法。
判断该字符串是否匹配指定的正则表达式
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
将该字符串中所有匹配regex的子串替换成replacement
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
将该字符串中第一个匹配regex的子串替换成replacement
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
以regex作为分隔符,把该字符串分割成多个子串
public String[] split(String regex) {
return split(regex, 0);
}
从源码可以看到String类中这些方法实际上还是依赖于Pattern和Matcher两个专门用于提供正则表达式支持的类
我们定义的任意字符串都可以当成正则表达式使用,例如“abc”,它也是一个正则表达式,只是它只能匹配“abc”字符串。
创建正则表达式
正则表达式就是一个用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串。
正则表达式所支持的合法字符
正则表达式中的特殊字符
预定义字符
上面的7个预定义字符其实很容易记忆,d是digit的意思,代表数字;s是space的意思,代表空白;w是word的意思,代表单词。d、s、w的大写形式恰好匹配与之相反的字符。
方括号表达式
方括号表达式比前面的预定义字符灵活多了,几乎可以匹配任何字符。例如,若需要匹配所有的中文字符,就可以利用
[\\u0041-\\u0056]
形式,因为所有中文字符的Unicode值是连续的,只要找出所有中文字符中最小、最大的Unicode值,就可以利用上面形式来匹配所有的中文字符。
边界匹配符
正则表达式还提供了数量标识符,正则表达式支持的数量标识符有如下几种模式。
Greedy(贪婪模式)
数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。如果你发现表达式匹配的结果与预期不符,很有可能是因为你以为表达式只会匹配前面几个字符,而实际上它是贪婪模式,所以会一直匹配下去。
Reluctant(勉强模式)
用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。
Possessive(占有模式)
用加号后缀(+)表示,目前只有Java支持占有模式,通常比较少用。
三种模式的数量表示符
关于贪婪模式和勉强模式的对比,看如下代码
String str = "hello , java!";
//贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*", "&"));
//勉强模式的正则表达式
System.out.println(str.replaceFirst("\\w*?", "&"));
输出结果
& , java!
&hello , java!
使用正则表达式
一旦在程序中定义了正则表达式,就可以使用Pattern和Matcher来使用正则表达式。
Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为Pattern对象,然后再利用该Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留Matcher对象中,多个Matcher对象可共享一个Pattern对象。
//将一个字符串编译成Pattern对象
Pattern p = Pattern.compile("a*b");
//使用Pattern对象创建Matcher对象
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();//返回true
上面定义的Pattern对象可以多次重复使用。如果某个正则表达式仅需一次使用,则可直接使用Pattern类的静态matches方法
public static boolean matches(String regex, CharSequence input) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
return m.matches();
}
从源码可以看出,采用这个方法每次都需要重新编译新的Pattern对象,不能重复利用已编译的Pattern对象,所以效率不高。
Pattern是不可变类,可供多个并发线程安全使用。
正则表达式是一个功能非常灵活的文本处理工具,增加了正则表达式支持后的Java,可以不再使用StringTokenizer类(也是一个处理字符串的工具,但功能远不如正则表达式强大)即可进行复杂的字符串处理。