目录
1. 正则表达式基本介绍
正则表达式(regular expression,简写为regex),Java提供了正则表达式技术,专门用于处理类似文本问题,就是用某种模式去匹配字符串的一个公式。换句话说,正则表达式是对字符串执行模式匹配的技术。
2. 正则表达式语法
2.1 基本介绍
了解正则表达式中各种元字符的功能是灵活运用正则表达式的基础。
元字符从功能上可以分为:
- 限定符
- 定位符
- 字符匹配符
- 选择匹配符
- 分组组合和反向引用符
- 特殊字符
2.2 元字符
2.2.1 转义符 \\
说明:在使用正则表达式检索一些特殊字符时,需要用到转义符号。
提示:Java的正则表达式中,两个斜杠 \\ 代表其他语言的一个
注意:几个需要用到转义符的字符有:* + ( ) $ / \ ? [ ] ^ { }
代码示例:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//正则表达式_元字符_转义号
public class EX01 {
public static void main(String[] args) {
String content = "abc$(abc(123(";
//匹配( => \\(
String regStr = "\\("; //注意这里的双斜杠转义号
//创建正则表达式对象
Pattern pattern = Pattern.compile(regStr);
//创建匹配器 matcher,按照 正则表达式的规则 去匹配 content 字符串
Matcher matcher = pattern.matcher(content);
//matcher.find() 会根据指定的规则,定位满足规则的子字符串
//group(0) 表示匹配到的子字符串
while(matcher.find()) {
System.out.println("找到 " + matcher.group(0));
}
}
}
运行结果:
找到 (
找到 (
找到 (
2.2.2 字符匹配符
符号 | 含义 | 示例 | 解释 | 匹配的输入示例 |
---|---|---|---|---|
[ ] | 可接收的字符列表 | [abcd] | a、b、c、d中任意一个字符 | a |
[^] | 不接收的字符列表 | [^abc] | 除a、b、c之外的任意一个字符,包括数字与特殊符号 | d |
- | 连字符 | A-Z | A至Z中任意一个大写字母(包括A和Z) | A |
. | 匹配除 \n 以外的任何字符。 若要匹配 . 本身则需要使用 \\ | a…b | 以a开头,b结尾,中间为两个任意字符的长度为4的字符串 | abcb、a12b、a*#b |
\\d | 匹配单个数字字符,相当于[0-9] | \\d\\d\\d | 包含3个数字的字符串 | 123 |
\\D | 匹配单个非数字字符,相当于[^0-9] | \\D(\\d)* | 以单个非数字字符开头,后接任意个数数字字符串 | a、A123 |
\\w | 匹配单个数字、大小写字母字符,相当于[0-9a-zA-Z] | \\w\\w\\w | 长度为3的数字字母字符串 | 12a、bDc |
\\W | 匹配单个非数字、大小写字母字符,相当于[^0-9a-zA-Z] | \\W + \\d{2} | 以至少1个非数字字母字符开头、2个数字字符结尾的字符串 | #12、@#23 |
代码示例:(此处只示范了[a-z],其余类似,可自行尝试)
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//正则表达式_元字符_字符匹配符
public class EX02 {
public static void main(String[] args) {
String content = "a2cd6";
//匹配 a-z 之间任意一个字符
String regStr = "[a-z]";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()) {
System.out.println("找到 " + matcher.group(0));
}
}
}
运行结果:
找到 a
找到 c
找到 d
2.2.3 选择匹配符
符号 | 含义 | 示例 | 解释 | 匹配的输入示例 |
---|---|---|---|---|
| | 匹配 “|” 之前或之后的表达式 | ab|cd | ab或者cd | ab、cd |
2.2.4 限定符
用于指定其前面的字符和组合项连续出现多少次
符号 | 含义 | 示例 | 解释 | 匹配的输入示例 |
---|---|---|---|---|
* | 指定字符重复0次或n次 | (abc)* | 仅包含任意个abc的字符串 | abc、abcabc |
+ | 指定字符重复1次或n次(至少1次) | m + (abc)* | 以至少1个m开头,后接任意个abc的字符串 | mabc、mabcabc |
? | 指定字符重复0次或1次(至多1次) | m + (abc)? | 以至少1个m开头,后接0个或1个abc的字符串 | mabc、mm |
{n} | 只能输入n个字符 | [abcd]{3} | 由abcd中任意字母组成的长度为3的字符串 | abc、acd、bcd |
{n,} | 至少指定n个匹配 | [abcd]{3,} | 由abcd中字母组成的任意长度不小于3的字符串 | aab、abd、bbbdca |
{n,m} | 至少指定n个但不多于m个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3,不大于5的字符串 | abcd、aabbc |
代码示例: (此处只示范了a{3,4},其余类似,可自行尝试)
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//正则表达式_元字符_限定符
public class EX03 {
public static void main(String[] args) {
String content = "1122aaaaaahelloworld";
//注意: java匹配默认贪婪匹配,即尽可能匹配多的
String regStr = "a{3,4}"; //表示匹配 aaa 或 aaaa
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()) {
System.out.println("找到 " + matcher.group(0));
}
}
}
运行结果:
找到 aaaa
2.2.5 定位符
用于规定要匹配的字符串出现的位置
符号 | 含义 | 示例 | 解释 | 匹配的输入示例 |
---|---|---|---|---|
^ | 指定的起始字符 | ^[0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 | 123、4abc、55cde |
$ | 指定结束字符 | ^[0-9]+[a-z]+$ | 以至少1个数字开头,并以至少1个小写字母结尾的字符串 | 1a、123a |
\\b | 匹配目标字符串的边界 | ke\\b | 边界指的是字串间有空格或是该目标字符串的结束位置 | kexueke nke |
\\B | 匹配目标字符串的非边界 | ke\\B | 与\b相反 | kexueke nke |
2.3 非贪婪匹配
符号 | 解释 |
---|---|
? | 当该字符紧跟其他限定符后面时,匹配模式为“非贪婪的”。即匹配搜索到的尽可能短的字符串。例如:在字符串“1111”中,“1+?”只匹配单个“1”,而“1+”匹配所有“1” 。 |
2.4 分组、捕获、反向引用
概念介绍:
- 分组
可以用一个圆括号组成一个匹配模式,这样一个圆括号中的部分我们可以看作是 一个分组。 - 捕获
把分组匹配的内容保存到内存中以数字编号或显式命名的组里,方便之后引用。组0表示整个表达式,第一个出现的分组为组1,第二个为组2,以此类推。 - 反向引用
圆括号的内容被捕获后,之后便可以被使用,这个就叫反向引用。在正则表达式内部的反向引用 \\分组号,外部反向引用 $分组号。
常用的分组构造形式 | 解释 |
---|---|
(pattern) | 非命名捕获。捕获匹配的子字符串,编号从0开始 |
(?<\name>pattern) | 命名捕获。将匹配的子字符串捕获到1个组名称或编号名称中,用于name的字符串不能包含标点符号,且不能以数字开头 |
代码示例:(此处示范 匹配4个连续的相同数字)
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//正则表达式_反向引用
public class EX04 {
public static void main(String[] args) {
String content = "1111222abcdddd3333hello"; //目标字符串
//匹配连续4个的相同数字
String regStr = "(\\d)\\1{3}"; //正则表达式字符串
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()) {
System.out.println("找到 " + matcher.group(0));
}
}
}
运行结果:
找到 1111
找到 3333
2.5 三个常用类
java.util.regex 包主要包括以下3个常用类
-
Pattern 类
pattern 类没有公共构造方法,要创建一个 pattern 对象,调用其公共静态方法,它返回一个 pattern 对象。该方法接受一个正则表达式作为它的第一个参数。例如: Pattern r = Pattern.compile(pattern); -
Matcher类
Matcher 对象是对输入字符串进行解释和匹配的引擎。Matcher 也没有公共构造方法。需调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。 -
PatternSyntaxException
PatternSyntaxException 是一个非强制性异常类,它表示一个正则表达式模式中的语法错误。
3. 应用示例
3.1 示例1-电话号码
要求:验证输入的电话号码的格式是否正确
格式规定:必须以13,14,15,18 开头的11位数,比如 13550358888
(读者可根据自己的需求灵活变通,此处只是举个例子,不代表所有情况)
代码实现:
import java.util.Scanner;
import java.util.regex.Pattern;
//正则表达式_电话号码
public class EX07 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//输入需要判断的电话号码
System.out.print("Enter Phone number: ");
String content = input.nextLine();
//要求必须以13,14,15,18 开头的11位数
String regStr = "^1[3|4|5|8]\\d{9}$";
//判断格式是否正确
System.out.println("The number is: " + Pattern.matches(regStr, content));
input.close();
}
}
运行结果:
Enter Phone number: 13550358888
The number is: true
3.2 示例2-电子邮件
要求:验证输入的电子邮件格式是否合法
格式规定:
- 只能有一个@
- @前面是用户名,可以是 a-z A-Z 0-9 _ - 字符
- @后面是域名,且只能为英文字母,如 bilibili.com
代码实现:
import java.util.Scanner;
import java.util.regex.Pattern;
//正则表达式_电子邮件
public class EX08 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//输入需要判断的电子邮件
System.out.print("Enter email: ");
String content = input.nextLine();
String regStr = "[\\w-]+@([a-zA-Z]+\\.)+[a-zA-Z]+";
//判断格式是否正确
System.out.println("The email is: " + Pattern.matches(regStr, content));
input.close();
}
}
运行结果:
Enter email: java@abcd.com
The email is: true
4. String类中使用正则表达式
4.1 替换字符串
String 类中包含的 replaceAll 方法可以替换所有匹配的字符串。
代码示例:(此处演示使用正则表达式来替换字符串)
//正则表达式_替换字符串
public class EX05 {
public static void main(String[] args) {
String content = "Java8abcdJava11defgjava";
//使用正则表达式,将Java8和Java11替换成Java
content = content.replaceAll("Java8|Java11", "Java");
//输出替换后的字符串
System.out.println(content);
}
}
运行结果:
JavaabcdJavadefgjava
4.2 分割字符串
String 类 public String[] split(String regex)
代码示例:(此处演示 如何按照 - 或者 ~ 或者 数字 来分割字符串)
//正则表达式_分割字符串
public class EX06 {
public static void main(String[] args) {
String content = new String("jike~hello-world234java");
//要求按照 - 或者 ~ 或者 数字 来分割
String[] split = content.split("-|~|\\d+");
for(String s : split) {
System.out.println(s);
}
}
}
运行结果:
jike
hello
world
java
以上为个人自学笔记,学习并借鉴了视频:https://www.bilibili.com/video/BV1Eq4y1E79W?p=1
以及Java黑皮书: Java语言程序设计与数据结构 基础篇
若有不足,欢迎指正!