一、概述
本篇文章将讲述Java正则表达式中的一些知识,正则表达式的用处主要有两个,第一是用来判断字符串,第二是用来爬取文本中的内容,由于本人学识浅薄,文中可能会出现错误或不足之处,恳请读者批评指正。
二、正则表达式中的字符
(一)字符类匹配字符
符号 | 解释 |
[ ] | 用来匹配一个字符,如[abc]可用来匹配a或b或c |
^ | 表示除了....., 比如[^abc]便是匹配除了a,b,c的其他字符 |
[a-zA-Z] | 表示可以匹配a-z的字母和A-Z的字母 |
[a-z&&[^ab]] | 表示可以匹配c-z的字符 |
示例:
public class Test1 {
public static void main(String[] args) {
String regex1 = "[abc]";
System.out.println("a".matches(regex1));//true
System.out.println("abc".matches(regex1));//false
String regex2 = "[^abc]";
System.out.println("a".matches(regex2));//false
System.out.println("b".matches(regex2));//false
System.out.println("c".matches(regex2));//false
System.out.println("h".matches(regex2));//true
String regex3 = "[a-zA-Z]";
System.out.println("a".matches(regex3));//true
System.out.println("A".matches(regex3));//true
System.out.println("@".matches(regex3));//false
String regex4 = "[a-z&&[^ab]]";
System.out.println("a".matches(regex4));//false
System.out.println("b".matches(regex4));//false
System.out.println("c".matches(regex4));//true
}
}
(二)预定义字符
符号 | 解释 |
. | .可以匹配出\n之外的任意一个字符 |
\d | 可以用来匹配0-9的数字字符 |
\s | 用来匹配空白字符(空格符、制表符、换行符等) |
\S | \S等价于[^\s] |
\w | 可以匹配数字、字母、下划线,即[0-9a-zA-Z _ ] |
\W | 等价于[^\w] |
注:写正则表达式时,\d等应写为\\d,总之记住java中两个\相当于一个\
示例:
public class Test2 {
public static void main(String[] args) {
String regex1 = ".";
System.out.println("a".matches(regex1));//true
System.out.println("&".matches(regex1));//true
System.out.println("#".matches(regex1));//true
System.out.println("==================regex2===================");
String regex2 = "\\d";
System.out.println("0".matches(regex2));//true
System.out.println("5".matches(regex2));//true
System.out.println("a".matches(regex2));//false
System.out.println("==================regex3===================");
String regex3 = "\\w";
System.out.println("0".matches(regex3));//true
System.out.println("a".matches(regex3));//true
System.out.println("_".matches(regex3));//true
System.out.println("#".matches(regex3));//false
System.out.println("==================regex4===================");
String regex4 = "\\W";
System.out.println("0".matches(regex4));//false
System.out.println("a".matches(regex4));//false
System.out.println("_".matches(regex4));//false
System.out.println("#".matches(regex4));//true
System.out.println("==================regex5===================");
String regex5 = "\\s";
System.out.println(" ".matches(regex5));//true空格
System.out.println("\t".matches(regex5));//true制表符
System.out.println("\n".matches(regex5));//true换行符
System.out.println("==================regex6===================");
String regex6 = "\\S";
System.out.println(" ".matches(regex6));//false
System.out.println("\t".matches(regex6));//false
System.out.println("\n".matches(regex6));//false
}
}
(三)用来控制匹配的字符数量
如果要匹配的字符串中有多个相同的部分的话,如果还按上面的写法就比较麻烦,比如要匹配字符串“abcdefgh”,我们的正则表达式就要写成“abcdefgh”或“\\w\\w\\w\\w\\w\\w\\w\\w”等都是非常复杂的,下面的内容便可解决这个问题。
符号 | 解释 |
{n} | 表示可以匹配n个字符,a{n}则可以等价于aaaaaa |
{n,} | 表示可以匹配大于等于n个字符 |
{n,m} | 可以匹配的字符数量大于等于n,小于等于m |
? | a?表示0个或1个a |
* | a*表示大于等于0个a |
+ | a+表示大于等于1个a |
示例:
public class Test3 {
public static void main(String[] args) {
System.out.println("abcdefgh".matches("abcdefgh"));//true
String regex = "\\w{8}";
System.out.println("abcdefgh".matches(regex));//true与上一种写法效果相同,但这种更加简洁
}
}
(四)分组的概念
我们将一个()的内容称为一组,组号从1开始,从左向右数
(1)捕获分组
我们要将某一组的内容重复使用,也就是捕获分组
第一种用法 \\组号,这种在同一个正则表达式中使用:
public class Test5 {
public static void main(String[] args) {
String regex = "\\d+(\\.\\w+)\\1";
String str = "123.edu.edu";
System.out.println(str.matches(regex));//true
}
}
第二种用法 &组号,这种在正则表达式外部使用:
public class Test6 {
public static void main(String[] args) {
String str = "我12#爱26#你";//我们要把str转换成"我12爱26你“
String res = str.replaceAll("(\\d+)#", "$1");//上面的意思也就是我们要把汉字之间的#去掉,而仅保留数字(其实可以直接把#换为长度为零的字符串),
//正则表达式中的第一组便是数字,所以我们可以直接把匹配到的字符换为第一组的内容即可
System.out.println(res);//我12爱26你
}
}
(2)非捕获分组
根据例子可以对表格的内容更近一步的理解
符号 | 解释 |
(?:正则) | 匹配全部,获取全部 |
(?!正则) | 匹配不包含正则部分的字符串 |
(?=正则) | 匹配全部,但只获取前部分 |
基础版(此处主要先了解一些方法):
我们要从一串文本中,读取我所需要的信息,比如下面的一串文本,我们要从中读出单词型的字符串:
public class Test4 {
public static void main(String[] args) {
String str = "此外,Java语言还具有丰富的类库,包括网络、数据库、图形、XML处理等功能,可以快速开发各种应用。"+
"Java的应用领域广泛,包括移动应用、软件开发、第三方交易系统以及大数据技术等。例如,在移动应用领域,许多Android手机应用都是使用Java语言编程完成的。"+
"Java语言在过去的二十多年里经历了多次演变和改进,不断提升简洁性、安全性,并支持大数据和云计算等新兴技术趋势。随着技术的不断发展,Java语言的未来仍充满潜力。";
String regex = "\\w+";
Pattern pattern = Pattern.compile(regex);//创建正则表达式的对象
Matcher matcher = pattern.matcher(str);//创建匹配器对象,可以理解为按照pattern的格式,在str中查找
while(matcher.find()){//如果第str中有符合条件的子串则find()返回true,并记下子串的起始和终止位置,否则返回false
System.out.println(matcher.group());//group()方法便是,按照find()记下的位置切割字符串,返回切割的字符
}
}
}
结果:
中级版:
(注:下面的java单词忽略大小写)
对上一字符串做一些修改(在部分Java单词的后面加上数字),为了区分读出来的是哪个java,我把它们的大小写字母改成了不同的, 要求:
(1)我们要读出所有后面有数字的Java字母,并且带上其后面的数字打印,如Java11
public class Test5 {
public static void main(String[] args) {
String str = "此外,java语言还具有丰富的类库,包括网络、数据库、图形、XML处理等功能,可以快速开发各种应用。"+
"Java11的应用领域广泛,包括移动应用、软件开发、第三方交易系统以及大数据技术等。例如,在移动应用领域,许多Android手机应用都是使用JAva8语言编程完成的。"+
"JAVa17语言在过去的二十多年里经历了多次演变和改进,不断提升简洁性、安全性,并支持大数据和云计算等新兴技术趋势。随着技术的不断发展,JAVA7语言的未来仍充满潜力。";
String regex = "(?i)java(?:\\d+)";//(?!)表示忽略后面所有字母的大小写,第二个问号可以理解成我们前面所匹配到的java,冒号代表获取子串时,连同后面的数字一同获取,就是说我们要获得的字符串类型就是java\\d+
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
System.out.println(matcher.group());
}
}
}
/*
结果:
Java11
JAva8
JAVa17
JAVA7
*/
(2)我们要读出所有后面没有数字的Java字母
public class Test6 {
public static void main(String[] args) {
String str = "此外,java语言还具有丰富的类库,包括网络、数据库、图形、XML处理等功能,可以快速开发各种应用。"+
"Java11的应用领域广泛,包括移动应用、软件开发、第三方交易系统以及大数据技术等。例如,在移动应用领域,许多Android手机应用都是使用JAva8语言编程完成的。"+
"JAVa17语言在过去的二十多年里经历了多次演变和改进,不断提升简洁性、安全性,并支持大数据和云计算等新兴技术趋势。随着技术的不断发展,JAVA7语言的未来仍充满潜力。";
String regex = "(?i)java(?!\\d+)";//与上题相比这里只把!改为了:,表示我们匹配时不匹配后面有数字(\\d)的字符串
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
System.out.println(matcher.group());
}
}
}
//结果:
//java
(3)我们要读出所有Java字母,并不读出其后的数字
public class Test7 {
public static void main(String[] args) {
String str = "此外,java语言还具有丰富的类库,包括网络、数据库、图形、XML处理等功能,可以快速开发各种应用。"+
"Java11的应用领域广泛,包括移动应用、软件开发、第三方交易系统以及大数据技术等。例如,在移动应用领域,许多Android手机应用都是使用JAva8语言编程完成的。"+
"JAVa17语言在过去的二十多年里经历了多次演变和改进,不断提升简洁性、安全性,并支持大数据和云计算等新兴技术趋势。随着技术的不断发展,JAVA7语言的未来仍充满潜力。";
String regex = "(?i)java(?=\\d+)";//这里也表示我们要获得的字符串类型为java\\d+即java后面跟有数字,但与上面第一题相比,冒号变为了=,表示我们在获取时并不获取后面的数字,而只获取java字母
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
System.out.println(matcher.group());
}
}
}
/*
结果:
Java
JAva
JAVa
JAVA
*/