正则表达式(JAVA)【提升字符串处理能力的利器】

偷偷发博客应该没有人会看见吧 😕,如果有写错的地方欢迎指正,第一次发博客,难免有些生疏,请大家谅解。

正则表达式(JAVA语言描述)

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

一、概念

​ 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

二、介绍

​ 正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

​ 上面的概念和介绍来自于百度,正则表达式_百度百科 (baidu.com),从描述中可见,正则表达式可以很方便地对字符串进行检索和替换,可以方便我们对于文本字串的操作。

​ 接下来我们将使用JAVA语言来进行正则表达式的学习。

JAVA正则使用流程:

​ 1、定义文本字串(String)content:

String content = "数论早期称为算术。到20世纪初,才开始使用数论的名称,";

​ 2、创建正则字符串(正则表达式):

String regStr = "\\d\\d";

​ 3、创建模式对象:

Pattern pattern = Pattern.compile(regStr);

注意::

在这里插入图片描述

这里使用的是java.util.regex中的pattern,而不是下面的包。

​ 4、创建匹配器(创建匹配器matcher,按照正则表达式的规则去匹配content字符串)

Matcher matcher = pattern.matcher(content);

​ 5、输出匹配内容:

while (matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

​ 输出:

​	[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1f5lpbms-1651672474687)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503205437067.png)]

三、特点

​ 正则表达式的特点是:

\1. 灵活性、逻辑性和功能性非常强;

\2. 可以迅速地用极简单的方式达到字符串的复杂控制。

\3. 对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、[Visual Studio](https://baike.baidu.com/item/Visual Studio/539453)等大型编辑器,都可以使用正则表达式来处理文本内容。

四、正则表达式语法

元字符:

1、限定符

2、选择匹配符

3、分组组合和反向引用符

4、特殊字符

5、字符匹配符

6、定位符

元字符(Metacharacter)-转义号\

\\符号 说明:当在正则表达式中去检索含转义字符的字串时,需要用到转义符号,否则匹配不到结果,甚至会报错

在java正则表达式中,两个\\代表其他语言中的一个\

PS:不适用转义字符会报错:
在这里插入图片描述

使用转义字符后的正确输出:
在这里插入图片描述

为什么不用 ( 而是\\( ,因为在java语言的正则表达式中,两个斜杠\\代表其他语言中的一个斜杠\

使用转义字符的场景(常用):. * + ( ) $ / \ ? [ ] ^ { }

元字符-字符匹配符

符号示例解释
[ ]可接收的字符列表[efgh]e、f、g、h中的任意一个字符
[^]不接收的字符列表[^abc]除a、b、c以外的任意一个字符包括字母和特殊符号
-连字符(左边到右边的范围)A-Z任意单个大写字母
符号含义示例说明匹配输入
.匹配除\n以外的任何字符a…b以a开头,b结尾,中间包括2个任意字符的长度为4的字符串aaab、a#*b、a33b
\\d匹配单个数字字符相当于[0-9]\\d{3}(\\d)? 1包含三个或四个数字的字符串123、9876
\\D匹配单个非数字字符,相当于2\\D(\\d)* 3以单个非数字字符开头,后接任意个数字字符串a、A342
\\w匹配单个数字、大小写字母字符,相当于[0-9a-zA-Z_]、另外还有下划线字符。\\d{3}\\w{4}4以三个数字字符开头的长度为7的数字字母字符串234abcd、12345pe
\\W匹配单个非数字、大小写字母、下划线字符,相当于[^ 0-9a-zA-Z]\\W+\\d{2}5以至少1个非数字字母字符开头,两个数字字符结尾的字符串#29、#?@10
\\s匹配任何空白字符(空格、制表符等)
\\S与\\s相反,匹配任何非空白字符
\\.匹配.字符
例子1(小写字母):

演示字符匹配符的使用 :

一、字符串中找到所有小写字母:

String content = "ac123456sda61dx";
String RegStr = "[a-z]";

Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JPQIfYdF-1651672474688)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503205915868.png)]

例子2(除了小写字母之外):

[^a-z]表示除了小写字母之外其他都能匹配

String content = "ac123456abcABC61dx";
String RegStr = "[^a-z]";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
      System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jxmTGVeL-1651672474689)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503211302346.png)]

正则表达式默认大小写问题:

java中的正则表达式默认是区分大小写的,如何实现不区分大小写:

第一种[使用(?i)]:
正则说明
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
ab(?i)c表示只有b不区分大小写

不使用(?i)之前:

String content = "ac123456abcABC61dx";
String RegStr = "abc";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uoeTGHV5-1651672474689)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503210456141.png)]

使用(?i)之后:

String content = "ac123456abcABC61dx";
String RegStr = "(?i)abc";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-agsTpDcy-1651672474690)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503210549561.png)]

第二种不区分大小写方式(pattern.compile()方法中增加限定参数):

规定pattern.compile()方法中的第二个参数为Pattern.CASE_INSENSITIVE,表示匹配时不区分大小写

Pattern pattern = Pattern.compile(RegStr,Pattern.CASE_INSENSITIVE);
例子3(限定参数):

由例子2中增加限定参数Pattern.CASE_INSENSITIVE,使得匹配的时候不区分大小写。

String content = "ac123456abcABC61dx";
        String RegStr = "[^a-z]";
//        Pattern pattern = Pattern.compile(RegStr,Pattern.CASE_INSENSITIVE);
        Pattern pattern = Pattern.compile(RegStr,Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(content);

        while(matcher.find()){
            System.out.println("找到:"+matcher.group(0));
        }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6g9IxF23-1651672474690)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503211735624.png)]

例子4(匹配非数字):

匹配非数字:

String content = "ac123456abcABC61dx";
String RegStr = "\\D";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fGu1HmFc-1651672474691)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503212015701.png)]

例子5(匹配大小写英文字母、数字、下划线字符):

匹配大小写英文字母、数字、下划线字符:

String content = "abc_@ABC61$";
String RegStr = "\\w";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PlzwKSBQ-1651672474691)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503212301042.png)]

例子6(过滤空白和\t):

过滤掉段落中的空白字符和制表符:

String content = "abc_@ABC 61   $";
String RegStr = "\\S";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMYYppFT-1651672474692)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503213056159.png)]

注意:在对齐的情况下一个制表符等于四个空白字符:

这里每当有一个空白字符就会打印一次 找到:

String content = "abc_@A    BC61$";
String RegStr = "\\s";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);

while(matcher.find()){
    System.out.println("找到:"+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6tmxQoN3-1651672474692)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503213246897.png)]

注意:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QisUYca7-1651672474693)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503213508715.png)]

​ A和B中间的空部分是在A已经末尾对齐的情况下敲的Tab制表符键,如果不是对齐的话敲制表符就会强制到末尾对齐位置而不是空4个空白字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l0x7f03G-1651672474694)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503213905649.png)]

这里第二行1的后面敲的是制表符但实际只空出3个空白字符,第三行12的后面敲的是制表符但实际只空出2个空白字符,第四行开头就敲一个制表符空出4个空白字符,文本会每隔4个空白字符一次对齐,制表符的空白字符的数量其实要根据当前文本的位置来决定,而不是固定的4个字符。

元字符-选择匹配符:

选择匹配符相当于或运算符:

符号说明示例解释
|匹配"|"之前或之后的表达式ab|cdab或者cd

元字符-限定符:

用于指定其前面的字符和组合项连续出现多少次:

符号含义示例说明匹配输入
*指定字符出现0次或者n次(0-n)(abc)*仅包含任意个abc的字符串,等效于\w*abc、abcabcabc
+指定字符重复1次或者n次(至少一次)(0-n)m+(abc)*以至少一个m开头,后接任意个abc的字符串m、mabc、mabcabc
?指定字符重复0次或者1次(最多一次)m+abc?以至少一个m开头,后接ab或者abc的字符串mab、mabc、mmab、mmmabc
{n}只能输入n个字符[abcd]{3}由abcd中字母组成的任意长度为3的字符串abc、acb、cba
{n,}指定至少n个匹配[abcd]{3,}由abcd中字母组成的任意长度不少于3的字符串aab,bbc,aabbcc
{n,m}指定至少n个但不多于m个匹配[abcd]{3,5}由abcd中字母组成的任意长度不少于3、不大于5的字符串abc、bbcc、aacbc
例子1(1{4}):

1{4}

String content = "11111";
String RegStr = "1{4}";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-slGXRA8R-1651672474695)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503220642290.png)]

只会匹配前4个1,后面一个1不会匹配

例子2(匹配两位任意数字):
String content = "11111aa";
String RegStr = "\\d{2}";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxBQcjPX-1651672474696)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503220829480.png)]

例子3(贪婪匹配):

java默认匹配方式是贪婪匹配,尽可能匹配多的。

String content = "aaaaa";
String RegStr = "a{3,5}";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Y9gTd8t-1651672474696)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503221129042.png)]

String content = "aaaaaa";
String RegStr = "a{3,4}";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AIOcN0oi-1651672474696)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503221234779.png)]

例子4(?):

?也遵守贪婪匹配

String content = "a111aaa";
String RegStr = "a1?";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hlxY1w9r-1651672474697)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220503221727702.png)]

例子5(非贪婪匹配):
字符说明
当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。例如,在字符串"oooo"中,"o+?“只匹配单个"o”,而"o+“匹配所有"o”。
String content = "aaa1111";
String RegStr = "\\d+";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z6OWfJmW-1651672474698)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504190348929.png)]

String content = "aaa1111";
String RegStr = "\\d+?";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wnVORYBA-1651672474698)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504190410753.png)]

元字符-定位符:

符号含义示例说明匹配输入
^指定起始字符^[0-9]+[a-z]*以至少一个数字开头,后接任意个小写字母的字符串123、6aa、555efd
$指定结束字符^[0-9]\\-[a-z]+$以一个数字开头后接连字符-,并以至少一个小写字母结尾的字符串1-a
\\b匹配目标字符串 的边界han\\b这里说的字符串的边界指的是子串间有空格,或者是目标字符串的结束位置adssadkbahan nxhan
\\B匹配目标字符串的非边界abc\\B和\\b的含义相反12311abc abc123 1abc2
例子1(^起始字符):
String content = "12311aaa12345abc";
String RegStr = "^[0-9]+[a-z]*";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4bqMDqMI-1651672474698)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504092053508.png)]

例子2(^结束字符):

(限定范围)+$:代表以限定范围内的字符结尾的字符串

String content = "12311abc";
String RegStr = "^[0-9]+[a-z]+$";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tr07gAyj-1651672474699)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504092155280.png)]

例子3(\\b匹配边界字符串)

这里的边界既可以是整个字符串的最后,又可以是字符串空格间隔的子串的最后

String content = "12311abc abc123 abc 1abc2 ";
String RegStr = "abc\\b";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OqbxaCtJ-1651672474700)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504092600835.png)]

String content = "12311abc abc123 1abc2 ";
String RegStr = "abc\\b";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fNAB8YO4-1651672474700)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504092701958.png)]

例子4(\\B)

\\B与前面相反

String content = "12311abc abc123 1abc2 ";
String RegStr = "abc\\B";

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2enB1XUu-1651672474701)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504092916914.png)]

分组:

常用分组:
常用分组构造形式说明
(pattern)非命名捕获。捕获匹配的子字符串。编号为零的第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号的顺序从1开始自动编号
(?pattern)命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头,可以使用单引号代替尖括号,例如(?‘name’)
例子1(()分组):

使用()进行分组:

String content = "nbPlus1234 abs1314aaa 7777";
String RegStr = "(\\d\\d)(\\d)(\\d)";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
    System.out.println("find: "+matcher.group(1));
    System.out.println("find: "+matcher.group(2));
    System.out.println("find: "+matcher.group(3));
    
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wf1eUO5n-1651672474701)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504182632830.png)]

例子2(命名分组):
String content = "nbPlus1234 abs1314aaa 7777";
String RegStr = "(?<s1>\\d\\d)(?<s2>\\d)(?<s3>\\d)";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
    System.out.println("find: "+matcher.group(1));
    System.out.println("find: "+matcher.group(2));
    System.out.println("find: "+matcher.group(3));

    System.out.println("find<s1>: "+matcher.group("s1"));
    System.out.println("find<s2>: "+matcher.group("s2"));
    System.out.println("find<s3>: "+matcher.group("s3"));

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0WVCEzIt-1651672474702)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504182944024.png)]

特别分组:
常用分组构造形式说明
(?:pattern)匹配pattern但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“or”字符(|)组合模式部件的情况很有用。例如(interest(?:ed|ing)是比interested|interesting更经济的表达式
(?=pattern)它是一个非捕获匹配。例如’windows (?=95|2008|10)'匹配"windows 2008"中的windows但不匹配windows 3.1中的Windows
(?!pattern)该表达式与(?=pattern)正好相反,它是一个非捕获匹配,例如’windows (?!95|2008|10)'匹配windows 3.1中的Windows但不匹配"windows 2008"中的windows
例子1:
String content = "abc1sz abc2x abc3ada";
String RegStr = "abc1|abc2|abc3";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ar66eRq-1651672474702)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504184117559.png)]

String content = "abc1sz abc2x abc3ada";
String RegStr = "abc(?:1|2|3)";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jSx5A4A-1651672474703)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504184212881.png)]

上面的abc(?:1|2|3)等同于abc1|abc2|abc3,但是虽然表达式中有括号,但不进行分组

非捕获匹配:不会将字符串存入matcher.group(1)当中,也就是说非捕获分组中的分组不会存入到group数组当中去,如果去访问group(1)会产生错误。

String content = "abc1sz abc2x abc3ada";
String RegStr = "abc(?:1|2|3)";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
    System.out.println("find: "+matcher.group(1));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0XcmOXAx-1651672474703)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504185640707.png)]

五、应用实例:

根据上面的内容综合一个案例:

使用正则表达式验证网站的URL格式是否正确

//验证URL
String content="https://www.bilibili.com/anime/?spm_id_from=333.1007.0.0";
//[.]表示匹配.本身
String RegStr = "^(htt(?:p|ps)://)?([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
if(matcher.find()){
    System.out.println("匹配成功!");
}
else{
    System.out.println("匹配失败!");
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UzjbyXEq-1651672474704)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504193858858.png)]

^(htt(?:p|ps)://)?部分,匹配https://或者http://在开头或者省略掉的字符串。

([\\w-]+\\.)+部分,匹配www.和bilibili.

[\\w-]+部分,匹配com

(\\/[\\w-?=&/%.#]*)?$部分,匹配结尾/anime/?spm_id_from=333.1007.0.0

注意([ ]的问题):

其中写在[ ]内的特殊字符,不用进行转义(\\),匹配的就是本身,比如下面的例子;

不使用[]:

String content = "aaa1.1";
String RegStr = ".";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PcoBeB8u-1651672474704)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504194342049.png)]

使用[]:

String content = "aaa1.1";
String RegStr = "[.]";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tHTSGFqs-1651672474705)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504194406152.png)]

六、正则表达式常用类:

java.util.regex包主要包括一下三个类Pattern类、Matcher类和PatternSyntaxException

Pattern类:

pattern对象是一个正则表达式对象。Pattern类没有公共构造方法,要创建一个Pattern对象,调用其公共静态方法,它返回一个Pattern对象。该方法接受一个正则表达式作为它的第一个参数,比如:

Pattern pattern = Pattern.compile(pattern);
matches方法:

Pattern类的matches方法,用于整体匹配,在验证输入的字符串是否满足条件使用:

下面是matches的源码:

public static boolean matches(String regex, CharSequence input) {
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(input);
    return m.matches();
}

由源码可以看出matches封装了创建模式对象和创建匹配器两步,当我们只是验证字符串是否匹配,而不进行索取的情况下,可以使用matches简化我们的写法

例子1:

对于上面第五部分的应用实例(验证URL的那个),我们实际上可以使用matches来简化我们的代码:

//验证URL
String content="https://www.bilibili.com/anime/?spm_id_from=333.1007.0.0";
//[.]表示匹配.本身
String RegStr = "^(htt(?:p|ps)://)?([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$";

System.out.println("匹配结果:"+Pattern.matches(RegStr,content));

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oO2HSyND-1651672474705)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504201218906.png)]

同时matches也相当于给RegStr的前面加上^后面加上$(整体匹配),常用于验证登录信息验证,邮箱验证等场景。

Matcher类:

Matcher对象是对输入字符串进行解释和匹配的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher方法来获得一个Matcher对象

方法:

方法及说明
public int start()返回以前匹配的初始索引。
public int start(int group)返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
public int end()返回最后匹配字符之后的偏移量
public int end(int group)返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量
public boolean lookingAt()尝试将从区域开头的输入序列与该模式匹配。
public boolean find()尝试查找与该模式匹配的输入序列的下一个子序列。
public boolean find(int start) 重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列
public boolean matches()尝试将整个区域与模式匹配
public Matcher appendReplacement(StringBuffer sb,String replacement)实现非终端和添加替换步骤。
public StringBuffer appendTail(StringBuffer sb)实现终端添加和替换步骤
public String replaceAll(String replacement)替换模式与给定替换字符串相匹配的输入序列的每个子序列
public String replaceFirst(String replacement)替换模式与给定替换字符串相匹配的输入序列的第一个子序列
public static String quoteReplacement(String s)返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement方法一个字面字符串一样工作
public Matcher appendReplacement(StringBuffer sb, String replacement)实现非终端添加和替换步骤。
public StringBuffer appendTail(StringBuffer sb)实现终端添加和替换步骤。

常用:start(),end(),matches(),replaceAll()

例子1(start和end):
String content="hello jack tom cate hello ";
String RegStr = "hello";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("===============");
    System.out.println(matcher.start());
    System.out.println(matcher.end());
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WkEl248c-1651672474706)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504202308411.png)]

返回字符串匹配的开始和结束的索引值(下标)。

例子2(replaceAll()):

把hello替换成123

String content="hello jack tom cate hello ";
String RegStr = "hello";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
String newStr = matcher.replaceAll("123");
System.out.println(newStr);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdUOe5UD-1651672474706)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504203847433.png)]

replaceAll()返回的才是替换之后的字符串,原来的字符串不会改变(被替换)。

异常:

PatternSyntaxException:

PatternSyntaxException是一个非强制异常类,它表示一个正则表达式中的语法错误。

七、分组、捕获和反向引用

1、分组:

​ 我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看作是一个子表达式/一个分组

2、捕获:

​ 把正则表达式中子表达式/分组匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推,组0代表的是整个正则式。

3、反向引用:

​ 圆括号的内容被捕获之后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,这个我们称为反向引用,这种引用既可以是在正则 表达式内部,也可以是在正则表达式外部,内部反向引用**\\分组号**,外部反向引用**$分组号**

例子(反向引用):

匹配两个连续的数字:

//匹配两个连续相等的数字
String content = "123455 asc66 ssw88";
String RegStr = "(\\d)\\1";
Pattern pattern = Pattern.compile(RegStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
    System.out.println("find: "+matcher.group(0));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-afKPmYyR-1651672474706)(C:\Users\松直君\AppData\Roaming\Typora\typora-user-images\image-20220504210142356.png)]

匹配多个连续的数字:使用{数字}来增加反向引用的数量

//匹配5个连续相同的数字
String content = "155555 asc66666 ssw88";
String RegStr = "(\\d)\\1{4}";

在这里插入图片描述

反向引用分组内容:

//匹配个位与千位相同,十位与百位相同的数字
String content = "15445 asc6776 ssw8877";
String RegStr = "(\\d)(\\d)\\2\\1";

在这里插入图片描述

例子2(去掉结巴语):

首先去掉…

//去掉结巴语,去掉连续重复的汉字,去掉...
String content = "我我...要学学学学...编程";
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
System.out.println("content= "+content);

然后去掉重复的汉字:这里利用外部的反向引用$1

pattern = Pattern.compile("(.)\\1+");
matcher = pattern.matcher(content);
content = matcher.replaceAll("$1");
System.out.println("content= "+content);

这里的话可以使用一句话进行处理:

content = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
System.out.println("content = "+content);

这里表达的思路就是,获取重复子串的第一个字,使用第一个字去替换剩下的重复的整个子串。

八、在String类中使用正则表达式:

替换:

String 类public String replaceAll(String regex,String replacement){}

//把windows1.0和windows2.0替换成windows
String s = "windows1.0、windows2.0,";
s = s.replaceAll("windows1\\.0|windows2\\.0","windows");
System.out.println(s);

判断:

String类 public bollean matches(String regex){}

//验证以137 138开头的手机号码
String s = "13699998866";
if(s.matches("1(38|39)\\d{8}")){
    System.out.println("验证成功!");
}else{
    System.out.println("验证失败!");
}

//验证以137 138开头的手机号码
String s = "13899998866";
if(s.matches("1(38|39)\\d{8}")){
    System.out.println("验证成功!");
}else{
    System.out.println("验证失败!");
}

分割:

String类 public String[] split(String regex){}

//按照~-#或者数字来分割字符串
String s = "back~to-home9,#OK!";
String[] oks = s.split("#|-|~|\\d+");
for (String ss:oks) {
    System.out.println(ss);
}

参考视频:b站韩顺平

【韩顺平讲Java】Java 正则表达式专题 -正则 正则表达式 元字符 限定符 Pattern Matcher 分组 捕获 反向引用等_哔哩哔哩_bilibili
1672474710)]

(https://www.bilibili.com/video/BV1Eq4y1E79W?p=1)


  1. \\d{3}相当于\\d\\d\\d其中{3}表示一共有三个前面这样的字符串,(\\d)?代表含有0个或者是1个\\d这样的数字字符串 ↩︎

  2. 2
    [^ 0-9a-zA-Z_]: [^0-9a-zA-Z_] ↩︎ ↩︎

  3. (\\d)*代表代表含有0个或者是n个\\d这样的数字字符串 ↩︎

  4. 前面有三个数字,后面有由数字、大小写字母字符组成的长度为4的字符串 ↩︎

  5. 中间的+代表一个到多个\\W字符串 ↩︎

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值