Java正则表达式
笔记根据网络资料整理而成,有些注解写的是自己的理解,可能会错误,欢迎大神指正。
正则表达介绍
正则表达式是一种用于字符串模式匹配和替换的强有力的工具,通过使用一系列特殊字符形成字符串模板,来描述字符串集合。正则表达式使用一系列匹配操作符,形成比较简单的表达式。通过替换不同的通配符就能形成不同字符串。
正则表达式在实际应用中,主要有数据有效性(或者存在性)验证和数据内容替换两个用途。其中数据有效性被用来测试字符串是否符合某种规则。例如,可以对某个字符串进行检测,看看字符串中是否存在电话号码、邮箱地址、网络IP地址等内容。数据内容替换通常用来删除或替换特定子字符串。比如可以在文档中使用正则表达式来标记某些特定文字,将其全部删除或者替换为其他文字。
1、常用符号和含义
符号 | 表示含义 |
表示字符的符号 | |
. | 表示任意一个字符 |
\s | 空格字符(空格,换行,换页,制表符,回车) |
\S | 非空格字符,(同 [^\s]) |
\d | 一个数字,(相当于[0-9]) |
\D | 一个非数字的字符([^0-9]) |
\w | 一个单词字符,(相当于[a-zA-Z_0-9]) |
\W | 一个非单词的字符,[^\w] |
^ | 一行的开始 |
$ | 一行的结尾 |
\b | 一个单词的边界,匹配字符串两边的空串 |
\B | 一个非单词的边界 |
\G | 前一个匹配结束 |
[] | 匹配方括号内的一个字符 |
如:[abc]表示字符a,b,c中的任意一个(与a|b|c相同) [a-zA-Z]表示从a到z或A到Z当中的任意一个字符 | |
() | 标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "\(" 和 "\)" |
\< | 匹配任何词开头的空字符串 |
表示次数的符号 | |
* | 重复零次或更多次 |
如:a*匹配零个或多个a | |
+ | 重复一次或更多次(至少出现一次) |
如:a+匹配一个或多个a | |
? | 重复零次或一次(最多出现一次) |
如:a?匹配零个或一个a | |
{n} | 重复n次 |
如:a{4}匹配4个a | |
{n,} | 重复n次或更多次(至少出现n次) |
如:a{4,}匹配至少4个a | |
{n,m} | 重复n到m |
如:a{4,10}匹配4~10个a |
注:要匹配有特殊意义的字符都要加反斜杠"\"才表示特殊字符本身,如要匹配"."、"$",就要相应加上反斜杠,变为 "\."、"\$"。而java语言里面"\"本身是有特出含义的,要表示"\"就要再加上一个反斜杠变为"\\",才表示反斜杠本身。所以java正则表达式里面要匹配特殊含义的字符要同时加两个反斜杠。"\\."、"\\$"才是java程序中能真正表达匹配符号"."、"$"本身。
因此上面的通配符号,凡是带"\"在java程序中使用时都要变为两个即"\\",如表示匹配数字时要使用:"\\d"。
2、java正则表达式使用实例
2.1 相关类介绍
JDK中提供了正则表达式的标准类包(java.util.regex),为Java语言开发者提供了强大的正则匹配功能。具体的java.util.regex中包含了正则模式类(Pattern)、匹配器类(Matcher)、模式语法异常(PatternSyntaxException)3部分内容。
各个类的具体功能和作用如下。
1) 正则模式类(Pattern)是一正则表达式编译后的表现模式,Pattern类没有提供程序员直接使用的构造方法,因此不能用new操作符来创建Pattern对象。在Java中,需要调用Pattern类提供的compile静态方法,该方法接收一个正则表达式字符串作为参数。每个通过字符串制定的正则表达式经过编译,然后返回Pattern的一个实例对象。
2) 匹配器类(Matcher)是一个正则匹配器,依据Pattern对象作为匹配模式,对字符串展开匹配检查。使用中可以通过Pattern对象创建一个Matter对象。该Matcher对象可以依据这个Pattern定义的正则表达式去匹配字符串。
3) 模式语法异常(PatternSyntaxException)是正则模式语法异常对象,包含了正则表达式编译过程中发现的语法错误。该异常在正则表达式模式出现语法错误的时候被抛出。
运行一次正则匹配涉及的所有状态都在Matcher类中,所以一个Pattern可以被很多Matcher所共享,Pattern类的实例是不可改变的,并且线程安全的。
Matcher类提供3种方法来查询匹配的结果。
boolean matches():根据Pattern对整个字符串序列进行匹配。
boolean lookingAt():根据Pattern从字符串的开头匹配,不要求整个字符串序列和Pattern匹配。
boolean find():在整个字符串序列中,查找下一个与pattern相匹配的字符串。另外有一个带参数的函数boolean find(int start),表示从参数start下标处开始查找。
2.2应用步骤:
1) 引入java包:import java.util.regex;
2)使用方法:
构造一个模式
Pattern p=Pattern.compile("[a-z]*");//想要匹配的格式
建造一个匹配器
Matcher m=p.matcher(str);//匹配字符串str
使用查询匹配结果函数进行判断,如
Boolean b=m.matches();
2.2应用举例
1) 给定字符串中符合匹配规则的子字符串
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("aaa222bb333ccc111");
while(m.find()) {
System.out.println("Match \"" + m.group() +"\" at positions " + m.start()+"-"+(m.end()-1));
}
}
}
注:不带参数的find()函数是从头到尾寻找字符串匹配结果,寻找到匹配的子字符串即返回(或者扫描完整个字符串没有匹配结果返回false),而且每次调用是从上次已经扫描结束的地方开始继续寻找匹配结果,就是find next的意思。所以要想重新从头开始匹配要使用reset()函数。
利用while(m.find)可以扫描匹配整个字符串,同时利用group()函数就可以查看匹配的结果了。
3、相关使用详细扩展
3.1、Groups
java中返回符合正则表达式的字符串就要用到group(),group中记录了所有符合指定表达式的字符串 。可使用group查看更细致的匹配信息。
group是指里用括号括起来的一组表达式,每一层括号即为一个group,这样括号里面的正则表达式可以被外面的调用。group( 0 )表示整个表达式,group (1)表示第一个被括起来的group,以此类推。
例如A(B(C))D里面有三个group:group (0)是ABCD, group (1)是BC,group (2)是C。这样使用当使用匹配操作(find()、matches()等)后,调用group(1)返回的是与表达式BC匹配的字符串。也就说进行一次匹配操作后,可查看每个group匹配到的字符串。
Matcher的group相关函数:
public int groupCount( ) 返回matcher对象使用的匹配模式中group的数目。不包括group 0。
public String group( ) 返回上次匹配操作( 比方说find() )与group 0(整个表达式)匹配的字符串。
public String group(int i) 返回上次匹配操作与某个group匹配的子字符串。如果匹配成功,但是没能找到group,则返回null。
注:此函数是从跟整个表达匹配的字符串中截取的子字符串。
public int start(int group) 返回上次匹配的某个group的开始位置,不带参数表示匹配group 0(整个表达式)的开始位置。
public int end(int group) 返回上次匹配的某个group的结束位置,最后一个字符的下标加1。不带参数表示匹配group 0(整个表达式)的结束位置。
3.2、一个代码示例
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
try{
//创建正则表达式
Pattern pt=Pattern.compile("(a(b)?c)+.*");
//匹配字符串
Matcher mc=pt.matcher("acabcfasd");
System.out.println(mc.matches());
int count=mc.groupCount();
for(int i=0;i<=count;i++){
System.out.println("Match \""+mc.group(i)+"\" at positions "+mc.start(i)+"-"+(mc.end(i)-1));
}
}catch(PatternSyntaxException e){
System.out.println("正则表达式语法错");
}catch(IllegalStateException e){
//该异常在调用group()无匹配结果时会抛出
System.out.println("找不到匹配字符串");
}
}
}
输出结果:
true
Match "acabcfasd" at positions 0-8
Match "abc" at positions 2-4
Match "b" at positions 3-3
注:感觉带参数的group如group(i)的作用是从跟整个表达匹配的字符串中截取的子字符串。跟整个表达式不匹配的时候,调用group就会产生找不到匹配字符串的异常。
group(1)这里返回的是"abc"而不是"ac"因为group总是返回最近依次匹配到的字符串。也就是第一次匹配(a(b)?c)的时候group(1)里面存储的是"ac",当继续匹配的时候,又找到新的匹配字符串"abc",这样"ac"就被替换掉了。
3.3、Matcher类的其它方法
String replaceAll(String replacement) 用给定的replacement全部替代匹配的部分
注:不要使用"\"和"$",这样因为这两个字符有特殊含义,会产生错误,如果想用这个字符分割前面要加两个反斜杠。如"\\$"。
String repalceFirst(String replacement) 用给定的replacement替代第一次匹配的部分
appendReplacement(StringBuffer sb,String replacement)根据模式用replacement替换相应内容,并将匹配的结果添加到sb当前位置之后。
StringBuffer appendTail(StringBuffer sb) 将输入序列中匹配之后的末尾字串添加到sb当前位置之后。
示例:
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
Pattern p = Pattern.compile("\\d+"); // 正则表达式
String [] strs=p.split("aa11bb22cc33dd44ee");
System.out.println("以数字分割字符串结果:");
for(int i=0;i<strs.length;i++)
System.out.println(strs[i]);
Matcher m = p.matcher("aa11bb22cc33dd44ee"); // 操作的字符串
StringBuffer sb = new StringBuffer();
m.matches();
System.out.println("调用replaceAll: "+m.replaceAll("-"));
int i=0;
m.reset();
while (m.find()) {
m.appendReplacement(sb, "|");
i++ ;//字符串出现次数
}
System.out.println("添加尾部之前: "+sb.toString());
m.appendTail(sb);//从截取点将后面的字符串接上
System.out.println("添加尾部之后: "+sb.toString());
}
}
程序结果:
以数字分割字符串结果:
aa
bb
cc
dd
ee
调用replaceAll: aa-bb-cc-dd-ee
添加尾部之前: aa|bb|cc|dd|
添加尾部之后: aa|bb|cc|dd|ee
相关资料:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/package-summary.html