一.正则表达式的入门
正则表达式是一些特定支付组成的,代表一个规则,简化代码,以字符的形式体现规则
正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式的概念始于20世纪50年代,当时美国数学家StephenColeKleene正式提出了正则语言的概念。随着Unix文本处理工具的出现,正则表达式被普遍使用。
自20世纪80年代以来,存在不同的编写正则表达式的语法,其中一种是POSIX标准,另一种是广泛使用的Perl语法
入门程序:
我们需要简单校验一下中国的电话号码的合法性,有以下简单规则:
- 以数字1开头
- 长度为11位
- 中间不包括字符
使用自己写的代码程序校验:
public static void main(String[] args) {
//手写程序
System.out.println(checkPhoneNumber("17388268020"));//true
System.out.println(checkPhoneNumber(null));//false
System.out.println(checkPhoneNumber("12"));//false
System.out.println(checkPhoneNumber("12as6987412"));//false
}
//手动书写程序
public static boolean checkPhoneNumber(String number){
if (number == null){
return false;
}
if (number.length()!=11 || number.charAt(0)!='1'){
return false;
}
for (int i = 1; i < number.length(); i++) {
if (number.charAt(i) < '0' || number.charAt(i) >'9'){
return false;
}
}
return true;
}
使用正则表达式:
public static void main(String[] args) {
//正则表达式
System.out.println(checkNumberUseRegex("17388268020"));//true
System.out.println(checkNumberUseRegex(null));//false
System.out.println(checkNumberUseRegex("12"));//false
System.out.println(checkNumberUseRegex("12as6987412"));//false
}
//正则表达式
public static boolean checkNumberUseRegex(String number){
return (number!=null) && number.matches("[1]\\d{10}");
}
可以看到,代码很简单,很优雅,很简洁
就是有点看不懂,所以我们需要认识以下,一些正则表达式的符号
正则表达式的常用符号
1.字符类:只能匹配单个字符 ,[ ]
//1.字符类(只能匹配单个字符)
System.out.println("a".matches("[abc]")); //true 只能是a,b,c
System.out.println("e".matches("[abc]"));//false
System.out.println("d".matches("[^abc]")); //ture 不能是a,b,c
System.out.println("a".matches("[^abc]"));//false
System.out.println("b".matches("[a-zA-Z]"));//true 范围是a~z,A~Z
System.out.println("2".matches("[a-zA-Z]"));//false
System.out.println("k".matches("[a-z&&[^bc]]"));// ture 范围是a~z,但是不包括bc
System.out.println("b".matches("[a-z&&[^bc]]"));//false
System.out.println("ab".matches("[a-z]"));//false []只能匹配一个字符,第二字符是不能匹配的
2.预定义字符:只能匹配单个字符
. \d \D \s \S \w \W
//2.预定义字符(只匹配单个字符)
//
// . \d \D \s \S \w \W
System.out.println("马".matches("."));//ture " . " 可以匹配任意字符
System.out.println("马马".matches("."));//false 只能匹配单个字符
//使用\d等字符定义的时候,一定要注意\代表转义,所以使用\d等,需要在加一个\,将\d的\转换掉,即\\d
System.out.println("3".matches("\\d"));//ture \d => 0~9
System.out.println("a".matches("\\d"));//false a不是数字
System.out.println(" ".matches("\\s"));//ture \s:代表一个空白字符
System.out.println("a".matches("\\s"));//false
System.out.println(" ".matches("\\S"));//false \S代表非空格
System.out.println("a".matches("\\S"));//ture
System.out.println("a".matches("\\w"));//ture 字符数字下划线:a~z,A~Z,0~9,_
System.out.println("_".matches("\\w"));//ture
System.out.println("9".matches("\\w"));//ture
System.out.println("马".matches("\\w"));//false
System.out.println("马".matches("\\W"));//ture 不能是 字符数字下划线
System.out.println("a".matches("\\W"));//false
3.数量词
? * + {n} {n, } {n,m}
//3.数量词
//? * + {n} {n, } {n,m}
System.out.println("a".matches("\\w?")); //ture ? 0次或1次
System.out.println("".matches("\\w?"));// ture 没出现
System.out.println("abc".matches("\\?"));//false
System.out.println("abc12".matches("\\w*"));// * 代表 0次或多次
System.out.println("".matches("\\w*"));//ture
System.out.println("acb马".matches("\\w*"));//false
System.out.println("abc12".matches("\\w+"));//ture + 代表 1次或多次
System.out.println("".matches("\\w+"));//false
System.out.println("acb马".matches("\\w+"));//false 出现:非字符数字下划线
System.out.println("acb".matches("\\w{3}"));//ture 出现3 次
System.out.println("abc".matches("\\w{3,}"));//ture 大于等于3次
System.out.println("abc".matches("\\w{3,6}"));//ture 大于等于 3次 ,小于等于 6次
4.其它几个常用的符号
(?i):忽略大小写 | :或 ():分组
//4.其它几个常用的符号
//(?i)忽略大小写 | 或 ():分组
System.out.println("abc".matches("(?i)abc"));//ture a 被忽略大小写
System.out.println("Abc".matches("(?i)abc"));//ture
System.out.println("aBc".matches("ab(?i)c"));//false B没有被限制
System.out.println("abc".matches("123{3}|\\w{3}"));//ture 要么是123三个字符 或者 要么是字符数字下划线三个
System.out.println("123".matches("123{3}|\\w{3}"));//ture
System.out.println("马ac".matches("123{3}|\\w{3}"));//false
System.out.println("ababc".matches("(ab)+c"));//ture ab必须出现1次或多次
System.out.println("(acacb)".matches("(ab)+c"));//false
System.out.println("abab".matches("(ab)?"));//false ab出现0次或1次
二.正则表达式的应用
使用正则表达式来校验电话号码
//检测电话号码是否合规
//可能是座机,可能是手机
public static boolean checkPhone(String num){
//手机电话以1开始,第二位是3-7,长度一般是 11 位
//座机号码一般是0开始,前三位是区号,中间可有可无 -符号,后面长度为5-20
//号码全是数字,无字符
return (num !=null) && (num.matches("(1[3-7]\\d{9})|(0\\d{2}-?[1-9]\\d{3,20})"));
}
正则表达式的写法其实就是在找字符串的规律:
(1[3-7]\\d{9})|(0\\d{2}-?[1-9]\\d{3,20})
验证手机号:
首先在校验手机号码的时候,我们可以看到必须是以1开头的,所以正则表达式就需要在第一个位置占位1
而第二位我们也知道了只能在3~9中选择,因为我们并没有发现10,11,12开头的电话号码,所以第二位的取值区间也被限定了[3-9]
除开前两位数字以后,后面的就没什么要求了,除了全部都是数字没有其它的要求所以可以使用 \ \d 直接概括完
(1[3-7]\\d{9})
验证座机号:
中间是有一个 | 符号的,它的作用是 :或的意思,也就是前面不匹配的时候可以试着匹配后面部分,在思想上就是如果不是手机号就是座机号
对于座机号我们也需要按照,字符串的规则来制定正则表达式
首先座机号码一般是0开始的,所以正则表达式直接使用0先占位
前三位只要是数字就行,所以可以直接使用 \\d{2},在匹配随机的任意两位数字就可以了
中间区号有些是需要使用 - 符号分割的,但是有些座机号又没有,所以按需使用就可以了,也就是 - 可以出现,也可以不出现,使用?就可以匹配 0 次或 1次
后面的就全部是数字 \\ d就可以搞定,然后限制一下,后面最多,最少可以拥有多少位数字就完成了
(0\\d{2}-?[1-9]\\d{3,20})
使用正则表达式来校验邮箱账户
//验证邮箱账户是否合理
//1425ms@163.com
//2021373@qq.com
//235676ll@msf.com.cn 二级域名
public static boolean checkEmail(String email){
return (email!=null) && (email.matches("\\w{2,}@\\w{2,10}(\\.\\w{2,10})+"));
}
主要来来看看正则表达式部分:
\\w{2,}@\\w{2,10}(\\.\\w{2,10})+
在验证邮箱账户的时候,每个邮箱账户有一个很明显的特点,它是使用@符号进行分割的
@前面部分都是由数字字符下划线组成的自定义用户名
@后面部分就是高级域名,他一般指代的是公司和区域位置,如腾讯的qq.com,网易的163.com等
所以在写正则表达式的时候也需要利用@将邮箱账户直接划分成两部分
前部分可以直接利用\\w解决,因为都是字符数组之类的,只用划定一下长度区间就好了,但是一般自定义的账户都是没有做长度限制的,都是在2个字符以上就可以了
@后面部分是高级域名区和公司称谓,都是\\w直接解决,限定长度就可以了,但是注意要加 . 符号,但是在正则表达式中 .是通配的意思,所以需要转义 \\ .
由于高级域名可能有两级,如:.com.cn,所以限定 \\. \\w{2,10} + ,出现 1次,或多次就可以了
使用正则表达式来查找信息
Pattern类:
在Java中,Pattern
类是用于表示正则表达式的一个类,它属于 java.util.regex
包。Pattern
类提供了一种将正则表达式编译为可重用的模式的方法,并且可以通过这些模式执行各种匹配操作。
使用 Pattern
类,可以将正则表达式编译为 Pattern
对象,然后使用该对象创建 Matcher
对象,以便在特定的输入字符串上执行匹配操作。可以使用 Matcher
对象的各种方法来执行匹配、查找和替换等操作。
简单来讲:使用pattern类利用Pattern.compile()方法,需要将一个正则表达式模板传入,而pattern.compile()方法就会根据正则表达式模板生成一个pattern对象,在进行文本匹配的时候,就会反复调用这个文本模板
matcher方法:
在Java中,Pattern
类的 matcher()
方法用于创建一个 Matcher
对象。Matcher
对象用于在给定的输入字符串上执行匹配操作。
当你有一个编译好的 Pattern
对象时,你可以使用 matcher()
方法来创建一个 Matcher
对象,然后使用该对象的各种方法来执行匹配、查找和替换等操作。
使用matcher方法就可以反复的查找给定的一段文本中的类容,如果文本类容中有一段符合正则表达式,则就返回ture,我们还可以matcher.group()方法将这段匹配的文本内容拿出来
代码测试:
public static void main(String[] args) {
String data ="来黑马程序员学习Java\n"+
"电话:1866668888,18699997777\n"+
"或者联系邮箱: boniu@itcast.cn\n" +
"座机电话:01036517895,010-98951256\n" +
"邮箱: bozai@itcast.cn\n" +
"邮箱2:dleieo09@163.com\n"+
"热线电话:400-618-9090 , 400-618-4008,4006184000,4006189090";
//1.定义查询时数据规则,正则表达式
//电话号码,座机号码,邮箱
String regex ="(1[3-9]\\d{9})|(0\\d{2}-?[1-9]\\d{3,20})|(\\w{2,}@\\w{2,10}(\\.\\w{2,10}){1,2})|(400-?618-?[1-9]\\d{3,20})";
//2.利用pattern.compile方法构造处一个pattern对象,利用正则表达式的模板
Pattern pattern = Pattern.compile(regex);
//3.利用pattern.matcher传入数据后,构造一个matcher对象,它会反复利用正则表达式遍历数据文本
Matcher matcher = pattern.matcher(data);
//匹配上数据后就可以输出了
while (matcher.find()){
System.out.println(matcher.group());
}
}
正则表达式用来搜索替换内容,分割
替换内容使用replaceAll()方法:
public String replaceAll(String regex,String newStr)
其中regex参数需要传入的是一个正则表达式,而newStr则是需要替换的新字符串
按照正则表达式匹配上的文本,替换成新文本
// public String replaceAll(String regex,String newStr)
//按照正则表达式匹配上的文本,替换成新文本
String txt1 = "正则表达式是1254真的好用12563,并且7852简洁,就是99864有点555难";
//将数字全部去掉
String s1 = txt1.replaceAll("\\w+", "");
System.out.println(s1); //正则表达式是真的好用,并且简洁,就是有点难
进阶版:
String txt2 = "我我我喜喜喜欢欢编编编编编编程程程程程程";
//去掉多余的字符,每个字符只留下一个
String s2 = txt2.replaceAll("(.)\\1+", "$1");
//这里的\\1是分组的意思,表示1组,后面被替换的字符就是重出现的字符,也就是1组内的字符,使用$符 组号将其取出来
System.out.println(s2); //我喜欢编程
分割内容使用的是spilt()方法:
public String[] spilt(String regex)
其中regex参数也是正则表达式
按照正则表达式匹配的内容进行分割,并且返回一个分割后的数组
//public String[] spilt(String regex)
//按照正则表达式匹配的内容进行分割,并且返回一个分割后的数组
String txt3 = "原来你也玩原神3564a,不对,原神56688ooihb启动!";
//将汉字用非汉字分割成字符串数组
String[] s3 = txt3.split("\\w+");
System.out.println(Arrays.toString(s3));//[原来你也玩原神, ,不对,原神, 启动!]