JAVA基础学习day26--正则表达式
一、正则表达式
1.1、概述
符合一规则的表达式:用于专门操作字符串。
正则表达式则必须依靠Pattern类与Matcher类,这两个类都在java.util.regex包中定义。Pattern类的主要作用是进行正则规范的编写,而Matcher类主要是执行规范,验证一个字符串是否符合其规范。
Pattern:
正则表达式的编译表示形式。
指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher
对象,依照正则表达式,该对象可以与任意字符序列
匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。
因此,典型的调用顺序是
Pattern p = Pattern.compile("a*b"); Matcher m = p.matcher("aaaaab"); boolean b = m.matches();
Matcher:
通过解释 Pattern
对 character sequence
执行匹配操作的引擎。
通过调用模式的 matcher
方法从模式创建匹配器。创建匹配器后,可以使用它执行三种不同的匹配操作:
每个方法都返回一个表示成功或失败的布尔值。通过查询匹配器的状态可以获取关于成功匹配的更多信息。
二、正则规则-预定义字符类
2.1、规则-预定义字符类
常用正则规则
No.
|
规范
|
描述
|
No.
|
规范
|
描述
|
1
|
\\
|
表示反斜线(\)字符
|
2
|
\t
|
表示制表符
|
3
|
\n
|
表示换行
|
4
|
[abc]
|
字符a、b或c
|
5
|
[^abc]
|
除了a、b、c之外的任意字符
|
6
|
[a-zA-Z0-9]
|
表示由字母、数字组成
|
7
|
\d
|
表示数字0-9
|
8
|
\D
|
表示非数字[^0-9]
|
9
|
\w
|
表示字母、数字、下划线
|
10
|
\W
|
表示非字母、数字、下划线[^\w]
|
11
|
\s
|
表示所有空白字符(换行、空格等)
|
12
|
\S
|
表示所有非空白字符[^\s]
|
13
|
^
|
行的开头
|
14
|
$
|
行的结尾
|
15
|
.
|
匹配除换行符之外的任意字符
|
|
|
|
2.2、匹配规则
数量表示(X表示一组规范)
No.
|
规范
|
描述
|
No.
|
规范
|
描述
|
1
|
X
|
必须出现一次
|
2
|
X?
|
可以出现0次或1次
|
3
|
X*
|
可以出现0次、1次或多次
|
4
|
X+
|
可以出现1次或多次
|
5
|
X{n}
|
必须出现n次
|
6
|
X{n,}
|
必须出现n次以上
|
7
|
X{n,m}
|
必须出现n~m次
|
|
|
|
逻辑运算符(X、Y表示一组规范)
No.
|
规范
|
描述
|
No.
|
规范
|
描述
|
1
|
XY
|
X规范后跟着Y规范
|
2
|
X | Y
|
X规范或Y规范
|
3
|
(X)
|
做为一个捕获组规范
|
|
|
|
2.3、Pattern类的常用方法
No.
|
方法
|
类型
|
描述
|
1
|
public static Pattern compile(String regex)
|
普通
|
指定正则表达式规则
|
2
|
public Matcher matcher(CharSequence input)
|
普通
|
返回Matcher类实例
|
3
|
public String[] split(CharSequence input)
|
普通
|
字符串拆分
|
在Pattern类中如果要想取得Pattern类实例,则必须调用compile()方法。
2.4、Pattern常用方法
方法摘要 | |
---|---|
static Pattern |
compile(String regex) 将给定的正则表达式编译到模式中。 |
static Pattern |
compile(String regex,
int flags) 将给定的正则表达式编译到具有给定标志的模式中。 |
int |
flags()
返回此模式的匹配标志。 |
Matcher |
matcher(CharSequence input)
创建匹配给定输入与此模式的匹配器。 |
static boolean |
matches(String regex, CharSequence input)
编译给定正则表达式并尝试将给定输入与其匹配。 |
String |
pattern()
返回在其中编译过此模式的正则表达式。 |
static String |
quote(String s)
返回指定 String 的字面值模式 String 。 |
String[] |
split(CharSequence input)
围绕此模式的匹配拆分给定输入序列。 |
String[] |
split(CharSequence input,
int limit) 围绕此模式的匹配拆分给定输入序列。 |
String |
toString()
返回此模式的字符串表示形式。 |
2.5、边界匹配器
边界匹配器 | |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词边界 |
\B | 非单词边界 |
\A | 输入的开头 |
\G | 上一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符(如果有的话) |
\z | 输入的结尾 |
三、String对正则表达式的支持
3.1、常用方法
Matcher类的常用方法在
No.
|
方法
|
类型
|
描述
|
1
|
public boolean matches(String regex)
|
普通
|
字符串匹配
|
2
|
public String replaceAll(String regex,String replacement)
|
普通
|
字符串替换
|
3
|
public String[] split(String regex)
|
普通
|
字符串拆分
|
四、示例
4.1、验证用户输入不是QQ号
/* 验证用户输入不是QQ号 QQ号以1-9开头,5-15位长度 都是数字使用\d或者[0-9]表示数字完成 */ import java.util.*; import java.util.regex.*; class RegexDemo1 { public static void main(String[] args) { //声明一个扫描器的变量,来接收用户键盘输入 Scanner input=new Scanner(System.in); //接收输入数据 String qq=input.nextLine(); //调用校验 checkQQ(qq); } /* 校验QQ */ public static void checkQQ(String qq) { //定义正则 //String regex="^[1-9]\\d{4,14}$"; String regex="[1-9][0-9]{4,14}"; //获取Pattern对象 Pattern p=Pattern.compile(regex); //验证字符串内容是否符合正则 Matcher m=p.matcher(qq); //判断 if(m.matches()) { System.out.println(qq+"是合法的QQ!"); } else { System.out.println(qq+"不是合法的QQ!"); } } }
4.2、验证手机号码是不是正确
/* 验证手机号码是不是正确 手机号1开头,都是数字,长度11位 */ import java.util.regex.*; import java.util.*; class RegexDemo2 { public static void main(String[] args) { Scanner input=new Scanner(System.in); String mobile=input.nextLine(); checkMobile(mobile); } public static void checkMobile(String mobile) { //String regex="1[0-9]{10}"; String regex="^[1][0-9]{10}$"; Pattern p=Pattern.compile(regex); Matcher m=p.matcher(mobile); if(m.find()) { System.out.println(mobile+"是合法的手机号码!"); } else { System.out.println(mobile+"不是合法的手机号码!"); } } }
4.3、验证用户输入邮箱是否合法
/* 验证用户输入邮箱是否合法 */ import java.util.regex.*; import java.util.*; class RegexMail { public static void main(String[] args) { Scanner input =new Scanner(System.in); String email=input.nextLine(); checkMail(email); } public static void checkMail(String email) { //邮件正则 String regex="\\w+@\\w+(\\.\\w+)+"; //直接使用String类的方法来比较 boolean flag=email.matches(regex); //输出结果 System.out.println(email+"..."+flag); } }
4.4、字符串匹配
/* 字符串匹配 */ import java.util.regex.*; class RegextDemo3 { public static void main(String[] args) { String str="aoob"; String reg="ao?b"; boolean b=str.matches(reg);//false ?表示不出现或者最多只能出现一次 System.out.println(str+"......"+b); reg="ao+b";//o最少出现一次,可出现多次 b=str.matches(reg); System.out.println(str+"......"+b);//true str="ab"; reg="ao+b";//o必须最少出现一次, b=str.matches(reg); System.out.println(str+"......"+b);//false str="ab"; reg="ao*b";//可以不出现也可以出现多次 b=str.matches(reg); System.out.println(str+"......"+b);//true str="aooooooob"; reg="ao{4,}b";//o最少出现4次,可以更多次 b=str.matches(reg); System.out.println(str+"......"+b);//true reg="ao{4,6}b}";//o现象4-6次 b=str.matches(reg);//o出现了7次 System.out.println(str+"......"+b);//false } }
4.5、字符串切割
/* 切割 */ import java.util.regex.*; class RegexDemo2 { public static void main(String[] args) { split_Fun(); System.out.println("================"); split_Fun2(); System.out.println("================"); split_Fun3(); System.out.println("================"); split_Fun4(); System.out.println("================"); split_Fun5(); } /* 按空格切割 */ public static void split_Fun() { String str="zhangsan lisi wangwu zhaoliu"; String reg="\\s+";//\s表示空白字符也可以" +"表示 String [] arr=str.split(reg); //长度 System.out.println("长度"+arr.length); for(String s:arr) { System.out.println(s); } } /* 按一个元素多次重复出现切割 */ public static void split_Fun2() { String str="zhangsan.lisi..wangwu...zhaoliu"; String reg="\\.+"; String [] arr=str.split(reg); //长度 System.out.println("长度"+arr.length); for(String s:arr) { System.out.println(s); } } /* 双反斜杠\\\\ */ public static void split_Fun3() { String str="c:\\abc\\a.txt"; String reg="\\\\+"; String [] arr=str.split(reg); //长度 System.out.println("长度"+arr.length); for(String s:arr) { System.out.println(s); } } /* 按照叠词来切割 为了可以让规则被重用可以将规则封装为一个组 用()完成,组的出现都有编号 从1开始,想要使用已经有的组可以通过\n的形式来获取 n就是组的编号 */ public static void split_Fun4() { String str="erkktyqquioppdffyphhct"; //按照叠词来切割 String reg="(.)\\1"; //(.)表示组,\1捕获组, String [] arr=str.split(reg); //长度 System.out.println("长度"+arr.length); for(String s:arr) { System.out.println(s); } } /* 按重复元素切割 */ public static void split_Fun5() { String str="helloaaworkldbbbuiopccc"; //按照叠词来切割 String reg="(.)\\1+"; //(.)表示组,\1捕获组, String [] arr=str.split(reg); //长度 System.out.println("长度"+arr.length); for(String s:arr) { System.out.println(s); } } }
4.6、替换
/* 正则替换 */ import java.util.regex.*; class ReplaceAllDemo { public static void main(String[] args) { //字符串中的数字替换为#号 String str="wer123ty343232uio23232f889..ffdsaf4324qq"; String reg="\\d{4,}"; //4个以上的数字替换 replaceAll_Fun(str,reg,"#"); System.out.println("================="); String str1="erkktyqqquizzzzzzofffpeeenmcvvhss"; //将叠替换为$号 String reg1="(.)\\1+"; replaceAll_Fun(str1,reg1,"\\$"); System.out.println("================="); String str2="erkktyqqquizzzzzzofffpeeenmcvvhss"; //将叠替换为单个字符 String reg2="(.)\\1+"; replaceAll_Fun(str2,reg2,"$1"); //使用$获取组的内容 } public static void replaceAll_Fun(String str,String reg,String newStr) { //替换 str=str.replaceAll(reg,newStr); System.out.println(str); } }
4.7、获取
/* 获取:使用正则表达式 将字符串符合规则的子串取邮 1.将正则表达式封装成对象 2.让正则对象和要操作的字符串相关联 3.关联扣, 获取正则匹配引擎 4.通过引擎对象符合规则的子串操作,比如取出 */ import java.util.regex.*; class RegexDemo4 { public static void main(String[] args) { getDemo1(); System.out.println("==============="); } public static void getDemo1() { String str="ming tian jiu yao fang jia le , da jia. AWT HELLO"; String reg="\\b[A-Za-z]{3}\\b"; //按3个字母组成的单词获取\b表示单词边界 //将规则封装为对象 Pattern p=Pattern.compile(reg); Matcher m=p.matcher(str); //尝试查找与该模式匹配的输入序列的下一个子序列 while(m.find()) { //获取获取的组 System.out.println(m.group());//jiu yao jia jia System.out.println(m.start()+"...."+m.end()); } } }
4.8、示例
/* 将下列字符串转成:学要学编程 "我我...我我...我要...要要...学学学...学学...编编编...编程..程.程程...程...程"; 1.如果只想知道该字符是否符合规则--使用匹配 2.想要将已经有的字符串变成另一个字符串,替换 3.想要按照自定义方式,将字符串变成多个字符串,---切割-获取规则以外的字符串 4.想要拿到符合要求的字符串子串,----获取---获取符合规则的子串 */ import java.util.*; class RegexText { public static void main(String[] args) { String str="我我...我我...我要...要要...学学学...学学...编编编...编程..程.程程...程...程"; /* 替换 先将..去掉 再将重复的内容变成单个内容 */ str=str.replaceAll("\\.+","");//将.替换为""空字符串 System.out.println(str); str=str.replaceAll("(.)\\1+","$1");//使用组,替换 System.out.println(str); } }
4.9、替换,切割
/* 192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30 还按照字符串自然顺序,只要让它们每一段都 是3位即可。 1.按照每一段需要的最多的0进行补齐,那么每一段就会至少保证3位 2.将每一段只保留3位。这位的所有的IP地址都每一段3位 */ import java.util.*; import java.util.regex.*; class RegexText2 { public static void main(String[] args) { String ip="192.168.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30"; //为每一段数字前加2个0 ip=ip.replaceAll("(\\d+)","00$1"); System.out.println(ip); /*00192.00168.001.00254 00102.0049.0023.00013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030 */ //再次替换 ip=ip.replaceAll("0*(\\d{3})","$1"); System.out.println(ip); //192.168.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030 //切割 String [] arr=ip.split(" +"); /* Arrays.sort(arr); System.out.println(Arrays.toString(arr)); */ //或者使用TreeSet TreeSet<String> ts=new TreeSet<String>(); for(String s:arr) { ts.add(s); } //遍历Set集合 for(String s:ts) { //将前置0删除 System.out.println(s.replaceAll("0*(\\d+)","$1")); } /* 2.2.2.2 8.109.90.30 10.10.10.10 102.49.23.13 192.168.1.254 */ } }
五、爬虫
5.1、示例
/* 爬虫1 从页面爬邮箱 */ import java.io.*; import java.util.regex.*; import java.util.*; import java.net.*; class RegexTest1 { public static void main(String[] args) throws Exception { List<String> list=getMail(); for(String s:list) { System.out.println(s); } } public static List<String> getMail() throws Exception { //从指定网址http://www.hao123.com/ String uaddr="http://www.hao123.com/"; //转换为URL对象 URL url=new URL(uaddr); //获取URLConnection对象,并连接,再获取流 //openStream(),就是openConnection().getInputStream()是个字节流 //封装为字符缓冲流 BufferedReader br=new BufferedReader(new InputStreamReader(url.openStream())); //邮箱正则 String reg="\\w+@\\w+(\\.\\w+)+"; //获取封装对象 Pattern p=Pattern.compile(reg); List<String> list = new ArrayList<String>(); //开始读取流 String line=null; while ((line=br.readLine())!=null) { //获取正则校验对象 Matcher m=p.matcher(line); //获取 while (m.find()) { //获取组,并添加 list.add(m.group()); } } br.close(); //返回结果集 return list; } }
示例
/* 网页爬虫(蜘蛛) */ import java.io.*; import java.util.regex.*; class RegexTest3 { public static void main(String[] args) throws Exception { getMail(); } public static void getMail() throws Exception { BufferedReader br=new BufferedReader(new FileReader("d:\\mail.txt")); String mailReg="\\w+@\\w+(\\.\\w+)+"; Pattern p=Pattern.compile(mailReg); String line=null; while ((line=br.readLine())!=null) { Matcher m=p.matcher(line); while (m.find()) { System.out.println(m.group()); } } } } /* fdsfadsafdsfdsfsdf> abc@sina.com<fdslfdsfdsf;dsjfsdjf fdsfadsafdsfdsfsdf> fdsfads@sina.com<fdslfdsfdsf;dsjfsdjf fdsfadsafdsfdsfsdf> fdsaf@qq.com<fdslfdsfdsf;dsjfsdjf afdsaffadsfadfssafdsdfdsfsdf> abc@sina.com<fdslfdsfdsf;dsjfsdjf ffdsfadsafdsffdsfsdf> abc@163.com<fdslfdsfdsf;dsjfsdjf safdsfadsafdssffdsfsdf> abc@sina.com<fdslfdsfdsf;dsjfsdjf dsfdsfadsafdsfdsfsdf> fdsafdsc@sina.com<fdslfdsfdsf;dsjfsdjf fafdfdsfadsafdsfdsfsdf> weweq@sina.com<fdslfdsfdsf;dsjfsdjf fdsa>abc@sina.com<fdslfdsfdsf;dsjfsdjf fdsfadsafdsfdsfsdf> adsdsafdsc@sina.com<fdslfdsfdsf;dsjfsdjf safdsfadsafdsfdsfsdf> abc@sina.com<fdslfdsfdsf;dsjfsdjf dsafdfdsfadsafdsfdsfsdf> abc@sina.com;fdslfdsfdsf;dsjfsdjf ffdsfdsfadsafdsfdsfsdf> abc@sina.com <fdslfdsfdsf;dsjfsdjf dsdsasaffdsfadsafdsfdsfsdf> abc@sina.com <fdslfdsfdsf;dsjfsdjf */