韩顺平_循序渐进学Java零基础_第27章 正则表达式(P878 - P904)
第27章 正则表达式
878. 正则快速入门
Pattern pattern = Pattern.compile("[0-9]+");
Matcher matcher = pattern.matcher(content);
while (matcher.find())
System.out.println(matcher.group(0));
879. 正则需求问题
880. 正则底层实现1
881. 正则底层实现2
String regExp = "\\\\d\\\\d\\\\d\\\\d";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find())
System.out.println(matcher.group(0));
- 根据指定的正则表达式,从给定的字符串中依次定位出满足匹配要求的子串
- 定位到子串时将子串首字符下标和尾字符下标 +1 记录到 matcher 对象的属性 int[] groups 的 group[0] 和 group[1] 中
- 同时记录 matcher 对象的属性 oldLast 的值为group[1],下一次匹配从 oldLast 开始
882. 正则底层实现3
- 分组:在正则表达式中一对小括号表示一组,从 1 ······ n
String regExp = "(\\\\d)(\\\\d)(\\\\d)(\\\\d)";
- 分组过后,matcher 对象的属性 groups 数组的第 0,1 个元素依然记录子串首字符下标,尾字符下标 +1;下标从 2 开始往后的 groups 数组的元素,每相邻两个元素依次记录该组首字符下标,尾字符下标 +1 的下标值。比如说 2020 出现在给定字符串的第 323 ~ 326 位置,我们将字符串分成两组,
则有:
groups[0] = 323、groups[1] = 327;
groups[2] = 323、groups[3] = 325;
groups[4] = 325、groups[5] = 327
883. 正则转义符
- 正则表达式语法 - 元字符(Meta character)
- 限定符
- 选择匹配符
- 分组组合和反向引用符
- 特殊字符
- 字符匹配符
- 定位符
- 转义符 \\ \\ : 在我们需要使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果。在 Java 的正则表达式中,两个 \\ \\ 代表其它语言中的一个 \\ 。需要用到转义符的字符主要有以下几个:. * + ( ) $ / \\ ? [ ] ^
884. 正则字符匹配
符号 | 意义 | 示例 | 解释 |
---|
[ ] | 可接收的字符列表 | [efgh] | e、f、g、h 中的一个字符 |
[^] | 不接收的字符列表 | [^abc] | 除 a、b、c 外的任意字符 |
- | 连字符 | A-Z | 任意单个大写字母 |
. | 除 \\n 以外的任意字符 | a…b | a 开头,b 结尾,长度为 4 的字符串 |
\\ \\d | [0-9] | \\ \\d3(\\ \\d)? | 长度为 3 或 4 的数字字符串 |
\\ \\D | [^0-9] | \\ \\D(\\ \\d)* | 非数字开头,后接任意个数字字符 |
\\ \\w | [0-9a-zA-Z_] | \\ \\d3\\ \\w4 | 3 个数字字符开头长度为 7 的数字字母字符串 |
\\ \\W | [^0-9a-zA-Z_] | \\ \\W+\\ \\d2 | 至少 1 个非数字字母开头,2个数字字符结尾 |
\\ \\s | 任何空白字符 | \\ \\d\\ \\ s \\ \\D | 数字字符开头,夹一个空白字符,非数字结尾 |
\\ \\S | 任何非空白字符 | \\ \\S | 匹配所有的非空白字符 |
885. 字符匹配案例1
- Java 正则表达式实现不区分大小写的两种方式:
- (?i)abc:abc 都不区分大小写;a(?i)bc:bc 不区分大小写
- Pattern pattern = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
886. 字符匹配案例2
887. 选择匹配符
符号 | 意义 | 示例 | 解释 |
---|
| | 匹配 | 之前或之后的串 | ab|cd | ab 或 cd |
888. 正则限定符
符号 | 意义 | 示例 | 解释 |
---|
* | 字符出现 0 次或 n 次 | (abc)* | 含有任意个 abc 的字符串 |
+ | 字符出现 1 次或 n 次 | m+(abc)* | 至少 1 个 m 开头,后接任意个 abc |
? | 字符出现 0 次或 1 次 | m+abc? | 至少一个 m 开头,后接 ab 或 abc |
n | 指定长度 | [abcd]3 | abcd 中长度为 3 的子串 |
n, | 长度大于等于 n | [abcd]3, | abcd 中长度大于等于 3 的子串 |
n,m | 长度大于等于 n 小于等于 m | [abcd]3,5 | abcd 中长度大于等于 3 小于等于 5 的子串 |
- Java 匹配模式默认贪婪匹配,尽量匹配长度较长的串。例如:str = aaaa regExp = “\\ \\ 3,4”,则结果为 aaaa
889. 正则定位符
符号 | 意义 | 示例 | 解释 |
---|
^ | 指定起始字符 | ^[0-9]+[a-z] | 至少 1 个数字开头,后接任意个小写字母 |
$ | 指定结束字符 | ^[0-9]\\ \\ -[a-z]+$ | 至少 1 个数字开头,夹 -,保证小写字母结尾 |
\\ \\b | 目标字符串边界 | han\\ \\b | 以字符串结尾或其后有空格,不需要括号 |
\\ \\B | 字符串非边界 | han\\ \\B | 字符串其后无空格或不是结尾字符串 |
890. 捕获分组
String regExp = "(\\\\d\\\\d)(\\\\d)(\\\\d)";
- 命名分组:将匹配的子字符串捕获到一个组名称或编号名称中。用于 name 的字符串不能包含任何标点符号并且不能以数字开头。可用单引号代替尖括号
String regExp = "(?<name>\\\\d\\\\d)(?<name>\\\\d\\\\d)";
891. 非捕获分组
- 不能使用 mather.group[1] 或 matcher.group[2···] 获取结果
"industr(?:y|ies)" <=> "industry|industries"
"windows(?=95|98|2000)":从 windows95 || windows98 || windows2000 中匹配出 windows
"windows(?!95|98|2000)":不从 windows95 || windows98 || windows2000 中匹配出 windows
892. 非贪婪匹配
String regExp = "1+?";
893. 正则应用案例
String regExp = "[\\u4E00-\\u9FA5]";
894. 正则验证复杂URL
String regExp = "(((https|http)?://)?([a-z0-9]+[.])|(www.))\\\\w+[.|\\\\/]([a-z0-9]0,)?[[.]([a-z0-9]0,)]+((/[\\\\S&&[^,;\\u4E00-\\u9FA5]]+)+)?([.][a-z0-9]0,+|/?)";
895. Pattern类
boolean isMatch = Pattern.matches(regExp,content);
896. Matcher类
方法名 | 功能 |
---|
int start() | 返回匹配成功串的起始索引 |
int end() | 返回匹配成功串的结束索引 +1 |
String replaceAll(String) | 用参数替换正则表达式匹配到的字符串,并返回新字符串 |
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegularExpression
public static void main(String[] args)
String content = "hello hell hello";
String regExp = "hello";
Pattern pattern = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(content);
while (matcher.find())
System.out.print(matcher.start() + "\\t");
System.out.println(matcher.end());
String newString = matcher.replaceAll("李春雄");
System.out.println(newString);
897. 反向引用
- 分组:我们可以用圆括号组成一个比较复杂的匹配模式,那么每个圆括号的部分我们可以看作是一个分组(也称为一个子表达式)
- 捕获:把正则表达式中分组匹配到的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。从左往右,以分组的左括号为标志,第一个出现的分组的组号为 1,第二个为 2,以此类推。编号为 0 的组代表整个正则式
- 圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,我们称之为反向引用。这种引用既可以在正则表达式内部,也可以在正则表达式外部。正则表达式内部反向引用 \\ \\ 分组号,正则表达式外部反向引用 $ 分组号
898. 反向引用案例
String regExp = "(\\\\d)\\\\1";
String regExp = "(\\\\d)\\\\14";
String regExp = "(\\\\d)(\\\\d)\\\\2\\\\1";
String regExp = "\\\\d5-(\\\\d)\\\\12(\\\\d)\\\\22(\\\\d)\\\\32";
899. 结巴去重案例
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegularExpression
public static void main(String[] args)
String content = "我...我...我...要要要..要要.学....Java!";
String regExp = "\\\\.";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
System.out.println(content);
regExp = "(.)\\\\1+";
pattern = Pattern.compile(regExp);
matcher = pattern.matcher(content);
content = matcher.replaceAll("$1");
System.out.println(content);
900. 替换分割匹配
- String 类中使用正则表达式
- 替换功能:public String replaceAll(String regex,String replacement)
- 判断功能:public boolean matches(String regex)
- 分割功能:public String[] split(String regex)
901. 本章练习1
902. 本章练习2
903. 本章练习3
904. 正则内容梳理