进阶Java编程(6)正则表达式
正则表达式
通过之前一系列的分析可以发现,String是一个非常万能的类型,因为String不仅仅可以支持有各种字符串的处理操作,也支持有向各个数据类型的转换功能,所以在项目的开发之中,只要用户输入的信息基本上都用String表示。于是在向其他数据类型转换的时候,为了保证转换的正确性,往往需要对其进行一些复杂的验证处理。
1,认识正则表达式
现在假设有一个字符串要求先判断字符串是否有数字组成,如果由数字所组成则将其变为数字进行乘法计算。
1 public class Main { 2 public static void main(String[] args) { 3 String str="123"; 4 if(isNumber(str)){ 5 int num=Integer.parseInt(str); 6 System.out.println(num*2); 7 } 8 } 9 public static boolean isNumber(String str){ 10 //静态方法不需要实例化对象 11 char[] data =str.toCharArray(); 12 for(int x=0;x<data.length;x++){ 13 if(data[x]>'9' || data[x]<'0'){ 14 return false; 15 } 16 } 17 return true; 18 } 19 }
·范例:使用正则表达式来实现同样的效果 实际上这种验证的功能是非常简单的,但是如此简单的功能却需要开发者编写大量的程序逻辑代码,如果是更加复杂的验证呢?那么在这样的情况下,对于验证来讲最好的做法就是利用正则表达式来完成。
1 public class Main { 2 public static void main(String[] args) { 3 String str="123"; 4 if(str.matches("\\d+")){ 5 int num= Integer.parseInt(str); 6 System.out.println(num*2); 7 } 8 } 9 }
使用正则最大的特点在于方便进行验证处理,以及方便进行复杂字符串的修改处理。(代码生成器中的代码自动匹配补全就是使用的正则) 正则表达式最早是从Perl语言里面发展而来的,而后在JDK1.4以前如果要使用到正则表达式的相关定义则需要单独引入相关的【*.jar】文件,但是从JDK1.4之后,正则已经默认被JDK所支持,并且提供有一个java.util.regex开发包,同时针对于String类也进行了一些修改,使其可以有方法直接支持正则处理。
2,常用正则标记
如果要想进行正则的处理操作,那么就首先需要对常用的正则标记有所掌握,从JDK1.4开始提供有一个java.util.regex开发包,这个包里面有一个Pattern程序类,在这个程序类里面定义了有所有支持的正则标记。
正则符号 |
功能 |
例子 |
1,【数量:单个】字符匹配 |
||
任意字符 |
表示由任意字符组成 |
"ab".matches("ab")=true |
\\ |
匹配【\】 |
|
\n |
匹配【换行】 |
|
\t |
匹配【制表】 |
|
2,【数量:单个】字符集(可以从里面任选一个字符) |
||
[abc] |
表示可能是a、b、c中任意的一个 |
|
[^abc] |
表示不是由字母a、b、c中任意一个 |
|
[a-zA-Z] |
表示由任意一个字母所组成,不区分大小写 |
|
[0-9] |
表示由一位数字所组成 |
|
3,【数量:单个】简化字符集 |
||
. |
表示任意的一个字符 |
|
\d |
等价于[0-9]范围 |
|
\D |
等价于[^0-9]范围 |
|
\s |
匹配任意的一位空格,可能是空格、换行、制表符 |
|
\S |
匹配任意的非空格 |
|
\w |
匹配字母、数字、下划线,等价于[a-zA-Z_0-9] |
|
\W |
匹配非字母、数字、下划线,等价于[^a-zA-Z_0-9] |
|
4,边界匹配 |
||
^ |
匹配边界开始 |
|
$ |
匹配边界结束 |
|
5,数量表示:默认情况下只有添加数量单位才可以匹配多位字符 |
||
表达式? |
该正则可以出现0次或1次 |
|
表达式* |
该正则可以出现0次、1次或多次 |
|
表达式+ |
该正则可以出现1次或多次 |
|
表达式{n} |
表达式的长度正好为n次 |
|
表达式{n,} |
表达式的长度正好为n次以上 |
|
表达式{n,m} |
表达式的长度正好为n~m次 |
|
6逻辑表达式:可以连接多个正则 |
||
表达式X表达式Y |
X表达式之后紧跟上Y表达式 |
|
表达式X|表达式Y |
有一个表达式满足即可 |
|
(表达式) |
为表达式设置一个整体描述。可以设置数量单位 |
3,String类对正则表达式的支持
在进行正则表达式大部分处理的情况下都会基于String类来完成,并且在String类里面提供有如下与正则有关的操作方法。
No. |
方法描述 |
类型 |
描述 |
01 |
public boolean matches(String regex) |
普通 |
将指定字符串进行正则判断 |
02 |
public String replaceAll (String regex,String replacement) |
普通 |
替换全部 |
03 |
public String replaceFirst (String regex,String replacement) |
普通 |
替换首个 |
04 |
public String[] split(String regex) |
普通 |
正则拆分 |
05 |
public String[] split (String regex,int limit) |
普通 |
正则拆分成特定个数 |
下面通过具体的范例来对正则的使用进行说明。
·范例:实现字符串的替换(删除掉非字母与数字)
1 public class Main { 2 public static void main(String[] args) { 3 String str="ajfsdf45345as74fe.;'dsaf1231sadfeqw4"; 4 String regex="[^a-zA-Z0-9]+"; 5 System.out.println(str.replaceAll(regex,"")); 6 } 7 }
·范例:实现字符串的拆分
1 public class Main { 2 public static void main(String[] args) { 3 String str="ajfsdf45345as74fe.;'dsaf1231sadfeqw4"; 4 String regex="\\d+"; 5 String[] result=str.split(regex); 6 for(int i=0;i<result.length;i++){ 7 System.out.print(result[i]+"、"); 8 } 9 } 10 }
·范例:判断一个数据是否为小数,如果是小数则将其变为double类型 在正则处理的时候对于拆分与替换的操作相对容易一些,但是比较麻烦的是数据验证的部分。
1 public class Main { 2 public static void main(String[] args) { 3 String str="100.1"; 4 String regex="\\d+(\\.\\d+)?"; 5 System.out.print(str.matches(regex)); 6 } 7 }
·范例:现在判断一个字符串是否由日期所组成,如果是由日期组成则将其转为Date类型
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 public class Main { 4 public static void main(String[] args) throws Exception{ 5 String str="1991-06-06"; 6 String regex="\\d{4}-\\d{2}-\\d{2}"; 7 if(str.matches(regex)){ 8 Date dateFormat=new SimpleDateFormat(("yyyy-MM-dd")).parse(str); 9 System.out.println(dateFormat); 10 System.out.println(new SimpleDateFormat(("yyyy-MM-dd")).parse(str)); 11 //使用1次变成垃圾(匿名对象) 12 } 13 } 14 }
·范例:判断给定的电话号码是否正确 需要注意的是,正则表达式无法对里面的内容进行判断,只能对格式进行判断处理。
①电话号码:51283346、"\\d{7,8}"
②电话号码:01051283346、"(\\d{3,4})?\\d{7,8}"
③电话号码:(010)-51283346、"((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8}"
1 public class Main { 2 public static void main(String[] args) throws Exception{ 3 String str1="51283346"; 4 String str2="01051283346"; 5 String str3="(010)-51283346"; 6 String regex="((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8}"; 7 System.out.println(str3.matches(regex)); 8 } 9 }
·范例:验证email格式 既然可以使用正则进行验证了,那么下面就可以利用其来实现一个email地址格式的验证。
email的用户名可以由字母、数字、_所组成。
1 public class Main { 2 public static void main(String[] args) throws Exception{ 3 String str1="wanyu@mufasa.site"; 4 String str2="mldnjava888@mldn.cn"; 5 String str3="10001@qq.com"; 6 7 String regex="[a-zA-Z0-9]\\w+@\\w+\\.(cn|com|com.cn|net|gov|site)"; 8 System.out.println(str3.matches(regex)); 9 } 10 } 11 /** 12 * email的用户名可以由字母、数字、_、-所组成(不能使用下划线开头); 13 * email的域名可以由字母、数字、_、-所组成; 14 * 域名的后缀必须是.cn、.com、.net、.com.cn、.gov; 15 * 现在已经有其他域名开放了 16 * deom1: wanyu@mufasa.site 17 * demo2: mldnjava888@mldn.abc 18 * demo3: 10001@qq.com 19 * [a-zA-Z0-9]\\w+@\\w+\\.(cn|com|com.cn|net|gov) 20 */
4,java.util.regex包支持 现在这几种正则的匹配处理操作是最常见的几种处理形式。
虽然在大部分的情况下都可以利用String类实现正则的操作,但是也有一些情况下需要使用java.util.regex开发包中提供的正则处理类,在这个包里面一共定义有两个类:Pattern(正则表达式编译)、Matcher(匹配)。
①Pattern类提供有正则表达式的编译处理支持:public static Pattern compile(String regex)
也提供有字符串的拆分操作:public String[] split(CharSequence input)
1 import java.util.regex.Pattern; 2 public class Main { 3 public static void main(String[] args) throws Exception{ 4 String str="dasjk\nlfds454\t3d sa4fasfas5f46d78.cs.;','zxv'sdf1a3dsf5"; 5 String regex="[^a-zA-Z0-9]+"; 6 Pattern pattern=Pattern.compile(regex); 7 String[] result=pattern.split(str); 8 for(int i=0;i<result.length;i++){ 9 System.out.print(result[i]+"、"); 10 } 11 } 12 }//字符串的拆分是最简单的
public Matcher matcher(CharSequence input)当获取Matcher类的对象之后就可以利用该类中的方法进行如下操作: ②Matcher类,实现了正则匹配的处理类,这个类的对象实例化依靠Pattern类完成
·正则匹配:public boolean matches()
·字符串替换:public String replaceAll(String replacement)
·范例:字符串匹配&替换
1 import java.util.regex.Matcher; 2 import java.util.regex.Pattern; 3 public class Main { 4 public static void main(String[] args) throws Exception{ 5 String str="101"; 6 String regex="\\d+"; 7 Pattern pattern=Pattern.compile(regex);//编译正则表达式 8 Matcher matcher=pattern.matcher(str); 9 System.out.println(matcher.matches()); 10 } 11 }
1 //字符串替换 2 import java.util.regex.Matcher; 3 import java.util.regex.Pattern; 4 public class Main { 5 public static void main(String[] args) throws Exception{ 6 String str="101dsad1354asd3f6ds5a4d2s1f1231231adf12"; 7 String regex="\\D+"; 8 Pattern pattern=Pattern.compile(regex);//编译正则表达式 9 Matcher matcher=pattern.matcher(str); 10 System.out.println(matcher.replaceAll("")); 11 } 12 }
如果纯粹的是以拆分、替换、匹配三种操作为例根本用不到java.util.regex开发包,只依靠String类就都可以实现了。但是Matcher类中提供有一种分组的功能,而这种分组的功能是String不具备的。
1 import java.util.regex.Matcher; 2 import java.util.regex.Pattern; 3 public class Main { 4 public static void main(String[] args) throws Exception{ 5 //要求取出“#{内容}”标记中的所有内容 6 String str="INSERT INTO dept(deptno,dname,loc) VALUES(#{deptno},#{dname},#{loc})"; 7 String regex="#\\{\\w+\\}"; 8 Pattern pattern=Pattern.compile(regex);//编译正则表达式 9 Matcher matcher=pattern.matcher(str); 10 while (matcher.find()){//是否有匹配成功的内容 11 System.out.println(matcher.group(0).replaceAll("#|\\{|\\}","")); 12 } 13 } 14 }
java.util.regex开发包,如果不是进行一些更为复杂的正则处理是很难使用到的,而String类所提供的功能只适合于正则的基本操作。