正则表达式:
正则表达式可以用来判断一些字符串是否满足该正则表达式的内容,可以将正则表达式理解为一种规则,而可以用该规则来衡量一些字符串是否符合要求。书写正则表达式时,应按照正确的例子从左到右分析逻辑,依次书写。
以下为部分格式,详细请参考api文档:
以下为一个正则表达式的练习,判断字符串是否符合正则表达式
package com.itazhang.demo4;
import java.math.BigDecimal;
import java.util.regex.Pattern;
public class Test4 {
public static void main(String[] args) {
String str1 = "13112345678";
String str2 = "13112341575";
String str3 = "13112345678";
String str4 = "131123454556";
//创建正则表达式
String regex1 = "1[3-9]\\d{9}";
System.out.println("13112345678".matches(regex1));
System.out.println("13112341575".matches(regex1));
System.out.println("13112345678".matches(regex1));
System.out.println("131123454556".matches(regex1));
System.out.println("---------------1---------------");
//创建正则表达式
/*
第一部分:区号以0开头
第二部分:0开头以后还有2-3位的区号,用\\d{2,3}表示
第三部分:有些区号可能会有-,即用-?判断可能会有一次或没有-
第四部分:在-之后,不能以0开头,即[1-9]表示以1-9的一个数字开头
第五部分:后面可以为4-9个[0-9]区间的数字,即\\d{4,9}
*/
String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
String str5 = "020-2324242";
String str6 = "02122442";
String str7 = "027-42424";
String str8 = "0712-3242434";
System.out.println("020-2324242".matches(regex2));
System.out.println("02122442".matches(regex2));
System.out.println("027-42424".matches(regex2));
System.out.println("0712-3242434".matches(regex2));
System.out.println("---------------2---------------");
/*
第一部分:@之前的部分,即只要是数字和字母以及下划线就行,出现次数只要一次及以上就可以,即\\w+
第二部分:即@
第三部分:即@后面.前面的位置,此时应为2-6位的数字和字母(不含下划线),即[\\w&&[^_]]{2,6}
第四部分:即.以及.之后的部分,此时.在Java中默认为任意字符,如果要用.本身的含义,即使用\\.则表示.
而在.之后则是字母2-3个[a-zA-Z]范围的字母,例如:com,cn。但有些邮箱可能有多个.com.cn,此时就需要
将(.com)作为一个整体使其出现1-2次,即(\\.[a-zA-Z]{2,3}){1,2}此时正则表达式完成。
*/
String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
String str9 = "3232323@qq.com";
String str10 = "zhangsan@itcast.cnn";
String str11 = "dlei0009@163.com";
String str12 = "dlei0009@pci.com.cn";
System.out.println("3232323@qq.com".matches(regex3));
System.out.println("zhangsan@itcast.cnn".matches(regex3));
System.out.println("dlei0009@163.com".matches(regex3));
System.out.println("dlei0009@pci.com.cn".matches(regex3));
}
}
同理,以下为正则表达式的练习2,要求匹配用户名和身份证号
package com.itazhang.demo4;
public class Test5 {
public static void main(String[] args) {
//编写用户名是否满足要求:大小写字母,数字,下划线,一共4-16位
String regex1 = "\\w{4,16}";
String username1 = "1235_kk";
String username2 = "itazhang11";
String username3 = "it@azhang0";
System.out.println(username1.matches(regex1));
System.out.println(username2.matches(regex1));
System.out.println(username3.matches(regex1));
System.out.println("----------------1-------------------");
/*编写身份证号码是否满足要求:
1、18位,前17位任意数字,最后一位可以是大小写的x
*/
//可以写为[1-9]\\d{16}[xX\\d],也能写成[1-9]\\d{16}[\\d|(?i)x],这里的(?i)表示的忽略大小写
String regex2 = "[1-9]\\d{16}[xX\\d]";
String id1 = "212024200212135578";
String id2 = "21202420021213557x";
String id3 = "21202420021213557X";
String id4 = "21202420021213557a";
System.out.println(id1.matches(regex2));
System.out.println(id2.matches(regex2));
System.out.println(id3.matches(regex2));
System.out.println(id4.matches(regex2));
System.out.println("----------------2-------------------");
//但现实生活中身份证号码不会像以上这么简单,所以以下为现实的身份证号码正则表达式
String regex3 = "[1-9]\\d{5}(?:18|19|20)\\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\\d|30|31)\\d{3}[\\dXx]";
String id5 = "42092219731015461X";
String id6 = "210811196005132133";
System.out.println(id5.matches(regex3));
System.out.println(id6.matches(regex3));
}
}
而在实际应用中,正则表达式大部分是用来爬虫,利用正则表达式可以筛选信息的特质,能爬取我们想要的信息,以下为本地爬取信息的代码
package com.itazhang.demo5;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PaChongTest1 {
public static void main(String[] args) {
String str = "电话:18512516758,18512508907或者联系邮箱:boniu@itcast.cn,座机电话:01036517895,010-98951256邮箱: bozai@itcast.cn,热线电话:400-618-9090,400-618-4000,4006184000,4006189090";
//手机的正则表达式
Pattern pattern1 = Pattern.compile("1[\\d]{10}");
//邮箱的正则表达式
Pattern pattern2 = Pattern.compile("[a-z]{5}@[a-z]{6}\\.cn");
//热线电话的正则表达式
Pattern pattern3 = Pattern.compile("400(-?)618(-?)\\d{4}");
//座机电话的正则表达式
Pattern pattern4 = Pattern.compile("010(-?)\\d{8}");
pachong(pattern1,str);
System.out.println("--------1--------");
pachong(pattern2,str);
System.out.println("--------2--------");
pachong(pattern3,str);
System.out.println("--------3--------");
pachong(pattern4,str);
}
public static void pachong(Pattern pattern,String str){
//获取需要爬取的对象,用pattern规则去爬取大串得到子串
Matcher m1 = pattern.matcher(str);
while(m1.find()){
String temp1 = m1.group();
System.out.println(temp1);
}
}
}
在爬取的时候有时候会有一些限制要求,而根据这些限制要求,利用不同正则表达式的书写能满足相应的要求,如下:
package com.itazhang.demo5;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PaChongTest2 {
public static void main(String[] args) {
String str = "Java是世界上最好的语言,目前企业里使用的最多的就是Java8和Java11,因为这两个版本是长期支持的版本,但是相信不久的以后,Java17也能登上舞台";
/*
以下要求
需求1:爬取版本号为8,11,17的Java文本,但是只要]ava,不显示版本号。
需求2:爬取版本号为8,11,17的Java文本。正确爬取结果为: Java8 Java11 Java17 Java17需求3:爬取除了版本号为8,11,17的Java文本,
需求3:爬取除了版本号为8,11,17的Java文本
*/
//使用(?i)(Java)时,会忽略Java这个子串的大小写
//使用(Java)(?=8|11|17)则会匹配前面为Java,后面跟着8或11或17的子串,并只返回Java这个子串
Pattern p1 = Pattern.compile("(?i)(Java)(?=8|11|17)");
pachong(p1,str);
System.out.println("---------1------------");
//使用(?:8|11|17)则会找出后面跟相应数字的子串
Pattern p2 = Pattern.compile("(?i)(Java)(?:8|11|17)");
pachong(p2,str);
System.out.println("---------2------------");
//使用(?!8|11|17)则会找出Java文本后没有相数字的子串
Pattern p3 = Pattern.compile("(?i)(Java)(?!8|11|17)");
pachong(p3,str);
}
public static void pachong(Pattern p,String str){
Matcher m = p.matcher(str);
while(m.find()){
String temp = m.group();
System.out.println(temp);
}
}
}
而在爬虫中会有贪婪爬取和非贪婪爬取
//贪婪爬取,使用+时,Java中会默认的多爬取更符合相关正则表达式的子串
//非贪婪爬取,在ab+之后添加?,即ab+?,则会默认爬取最少符合该正则表达式的子串
代码如下:
package com.itazhang.demo5;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PaChongTest3 {
public static void main(String[] args) {
String str = "Java是世界上最好的语言,aaaaaaaaabbbbbaaaaaa目前企业里使用的最多的就是Java8和Java11,因为这两个版本是长期支持的版本,但是相信不久的以后,Java17也能登上舞台";
//贪婪爬取,使用+时,Java中会默认的多爬取更符合相关正则表达式的子串
Pattern p1 = Pattern.compile("ab+");
pachong(p1,str);
//非贪婪爬取,在ab+之后添加?,即ab+?,则会默认爬取最少符合该正则表达式的子串
Pattern p2 = Pattern.compile("ab+?");
pachong(p2,str);
}
public static void pachong(Pattern p, String str){
Matcher m = p.matcher(str);
while(m.find()){
String temp = m.group();
System.out.println(temp);
}
}
}
正则表达式也还有其他的使用场景,例如字符串里的replace方法和split方法
//使用replaceAll的方法将符合正则表达式的内容更改为相应内容
//使用split方法能将满足正则表达式的子串切割,将其他的子串用数组的方式返回
具体例子代码如下:
package com.itazhang.demo5;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PaChongTest4 {
public static void main(String[] args) {
String str = "我真的是_太TMD123tmd477有趣了哈哈哈TmdTmdtmd";
//使用replaceAll的方法将符合正则表达式的内容更改为相应内容
String s = str.replaceAll("[\\w&&[^_]]+", "1");
System.out.println(s);
//使用split方法能将满足正则表达式的子串切割,将其他的子串用数组的方式返回
String[] split = str.split("[\\w&&[^_]]+");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i] + " ");
}
}
public static void pachong(Pattern p, String str){
Matcher m = p.matcher(str);
while(m.find()){
String temp = m.group();
System.out.println(temp);
}
}
}
在正则表达式应用中会有存在捕获分组的情况,就是在正则表达式后面可能会用到该表达式前面的子串,例如判断aaa123aaa类型,后面的aaa会用到前面的aaa,即用\\1在正则表达式内部表示前面的第一组
实例代码如下:
package com.itazhang.demo5;
import java.util.regex.Pattern;
public class ZhengZhe {
public static void main(String[] args) {
//用分组能解决一些常见的字符串问题
String str = "abc123k1a";
//这里的\\1表示重新运用第一组,也就是(.)
String regex1 = "(.).+\\1";
System.out.println(str.matches(regex1));
//判断开始与结尾是否一致,可以有多个字符
String str2 = "abc123k1abc";
String regex2 = "(.+).+\\1";
System.out.println(str2.matches(regex2));
//判断开始结束的部分相同,其中部分里的元素相同例如aaa123aaa
String str3 = "aaa123aaa";
String str4 = "aaa123aab";
String regex3 = "((.)+).+\\1";
System.out.println(str3.matches(regex3));
System.out.println(str4.matches(regex3));
}
}
而有时候会在正则表达式外部使用正则表达式的第i组,用法如下
//此时的$1符号则是在正则表达式外部使用正则表达式中第一组的用法 String str2 = str.replaceAll(regex,"$1");
实例代码如下:
package com.itazhang.demo5;
public class ZhenZhe2 {
public static void main(String[] args) {
String str = "我是真真真的的的不不不不不不口吃吃吃吃啊";
//想要将上诉改为我是真的不口吃啊,会用到在正则外使用前一组的用法
String regex = "(.)\\1+";
//此时的$1符号则是在正则表达式外部使用正则表达式中第一组的用法
String str2 = str.replaceAll(regex,"$1");
System.out.println(str2);
}
}