Java正则表达式
1.概述
- 正则表达式是一种描述字符串模式的语言。
- 正则表达式可以用来搜索、编辑或处理文本。
- Java 提供了 java.util.regex 包,它包含了 Pattern 和 Matcher 类,用于处理正则表达式的匹配操作。
2.作用
- 验证用户输入的数据是否合法。[检验字符串是否满足某种格式]
- 提取数据中的有效信息。
- 替换字符串中的部分字符。[对文本进行格式化]
3.基本语法
符号 | 含义 | 例子 |
---|---|---|
[] |
里面的内容出现一次 | [a-z]: a-z之间的任意字符 |
() |
分组[按左括号计算组数,从1开始] | a(bc)+: bc为第一组,+ 作用在第一组(bc) 上 |
^ |
取反 | [^a-z]: 不是a-z之间的任意字符 |
&& |
交集,不能写单个的& |
[a-z&&[^bc]]: a-z之间的任意字符,但排除bc |
| |
写在方括号外面表示并集,不能写两个的|| |
[a-zA-Z]: a-z或A-Z之间的任意字符。 x|X: 大小写x都可以 。 注意: [a-z|A-Z]中的| 只是一个普通的字符,并不表示并集。 |
. |
任意字符[回车符号不匹配] | a.b: 可以是acb、a0b、a吖b等。 |
\ |
转义字符 | \\d : 匹配一个数字字符[0-9]。其中第一个\ 是用作转义字符,用于将后面的\ 转义成普通字符。第二个\ 后面紧跟着的d表示匹配一个数字字符。在正则表达式中,\d 是一个特殊的元字符,用于匹配数字字符。 |
\d |
数字 | \\d: 匹配一个数字字符[0-9]。 |
\D |
非数字 | \\D: 匹配一个非数字字符[^0-9]。 |
\s |
空格 | \\s: 匹配一个空白字符[ \t\n\x0B\f\r]。 |
\S |
非空格 | \\S: 匹配一个非空白字符[^ \t\n\x0B\f\r]。 |
\w |
字母数字下划线 | \\w: 匹配一个单词字符[a-zA-Z_0-9]。 |
\W |
非字母数字下划线 | \\W: 匹配一个非单词字符[^a-zA-Z_0-9]。 |
? |
0或1次[作用在前者] | a?b: ab或b。?作用在a上,表示a为可选字符。 |
* |
0或n次[作用在前者] | a*b: ab、abb、abbbb、…。*作用在a上,表示a为0或n次。 |
+ |
1或n次[作用在前者] | a+b: ab、abb、abbbb、…。+作用在a上,表示a为1或n次。 |
{n} |
n次[作用在前者,填写具体次数] | a{2}b: abb。{n}作用在a上,表示a为n次。 |
{n,m} |
n到m次[作用在前者,填写范围] | a{2,4}b: abb、abbb、abbbb。{n,m}作用在a上,表示a为n到m次。 |
{n,} |
n次及以上[作用在前者,填写范围] | a{2,}b: abb、abbb、abbbb、…。{n,}作用在a上,表示a为n次以上。 |
{,m} |
0到m次[作用在前者,填写范围] | a{,4}b: abb、abbb、abbbb、…。{,m}作用在a上,表示a为0到m次。 |
(?i) |
忽略大小写[作用在后者] | (?i)abc: 匹配abc或ABC、…。a((?i)b)c: 只忽略b的大小写。 |
[\u4E00-\u9FFF·] |
中文 | [\u4E00-\u9FFF·] |
Java的反斜杠
\
:
- 在其他语言中,\ 表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。
- 在 Java 中,\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。
所以,在其他的语言中(如 Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在 Java 的正则表达式中,两个 \\ 代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \\d,而表示一个普通的反斜杠是 \\。
System.out.print("\\"); // 输出为 \ System.out.print("\\\\"); // 输出为 \\
4.常用到的类
- Pattern: 正则表达式的编译表示。
- Matcher: 正则表达式的匹配表示。
4.1. Pattern类
Pattern
类表示正则表达式模式,并提供了一系列静态方法来编译和处理正则表达式。
- 编译正则表达式: 使用
Pattern.compile()
方法来编译正则表达式字符串,并返回一个Pattern
对象。Pattern pattern = Pattern.compile("ab+c");// 参数是你要匹配的正则表达式字符串。
4.2. Matcher类
Matcher
类用于对字符串进行匹配操作,并提供了一系列方法来执行匹配和检索操作。
-
创建Matcher对象: 使用
Pattern.matcher()
方法将要匹配的字符串与Pattern
对象相关联,创建一个Matcher
对象。Matcher matcher = pattern.matcher("abbbbbbcsa");// 参数是你要匹配的字符串。
-
匹配操作:
matches()
: 尝试将整个输入序列与模式匹配。find()
: 尝试查找输入序列中与模式匹配的子序列。group()
: 返回当前匹配的子字符串。
if (matcher.matches()) { System.out.println("Match found!"); }
-
检索操作:
start()
: 返回当前匹配的子字符串的起始索引。end()
: 返回当前匹配的子字符串的结束索引。
String text = "The quick brown fox jumps over the lazy dog."; // 匹配单词中的元音字母 Pattern pattern = Pattern.compile("the"); Matcher matcher = pattern.matcher(text); // 输出匹配的子字符串的起始和结束索引 while (matcher.find()) { System.out.println("Start index: " + matcher.start()); //输出: 31 -> 't' System.out.println("End index: " + matcher.end());// 输出: 34 -> ' ' }
-
替换操作:
-
replaceAll(String replacement)
: 将匹配的子字符串替换为指定的字符串。 -
replaceFirst(String replacement)
: 将匹配的第一个子字符串替换为指定的字符串。 -
appendReplacement(StringBuffer sb, String replacement)
: 将匹配的子字符串替换为指定的字符串,并将替换后的字符串添加到StringBuffer
或StringBuilder
对象中。 -
appendTail(StringBuffer sb)
: 将未匹配的子字符串添加到StringBuffer
或StringBuilder
对象中。
4.3. 正则表达式标志
正则表达式编译时可以使用一些标志来修改匹配的行为。这些标志通常作为第二个参数传递给Pattern.compile()
方法。
-
忽略大小写(CASE_INSENSITIVE / (?i)): 使匹配不区分大小写。
Pattern pattern = Pattern.compile("cat", Pattern.CASE_INSENSITIVE); // 或者 Pattern pattern = Pattern.compile("(?i)cat");
-
多行模式(MULTILINE / (?m)): 使
^
和$
匹配每行的开始和结束,而不是整个输入序列的开始和结束。Pattern pattern = Pattern.compile("^dog", Pattern.MULTILINE); // 或者 Pattern pattern = Pattern.compile("(?m)^dog");
-
单行模式(DOTALL / (?s)): 使
.
匹配包括换行符在内的所有字符。Pattern pattern = Pattern.compile(".*", Pattern.DOTALL); // 或者 Pattern pattern = Pattern.compile("(?s).*");
这些是一些常见的标志,但Java支持更多其他标志,可以根据需要使用。标志可以组合使用,例如Pattern.compile("pattern", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE)
。
5.捕获分组和非捕获分组
5.1. 捕获分组[后续还要继续使用本组的数据]
基本概念:
- 每组都是由
()
括起来。 - 捕获分组:捕获分组会记住匹配的文本,并可以在匹配后引用这些文本。
分组规则: - 从1开始,连续不间断
- 以左括号为基准,最左边的是第一组,其次为第二组,以此类推
使用规则: - 正则表达式内部使用: \\组号
- 正则表达式外部使用: $组号
5.2. 非捕获分组[分组后不再使用本组数据]
符号 | 含义 | 例子 |
---|---|---|
(?:regex) |
匹配regex ,获取所有文本,包括regex |
Java(?:8|11|17) |
(?=regex) |
匹配regex ,只获取前面部分文本,不包括regex |
Java(?=8|11|17) |
(?!regex) |
获取不匹配regex 的文本的前面部分,不包括regex |
Java(?!8|11|17) |
String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
"因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
//?: 匹配`regex`,获取所有文本,包括`regex`
String regex2 = "Java(?:8|11|17)";//Java8 Java11 Java17 Java17
//?= 匹配`regex`,只获取前面部分文本,不包括`regex`
String regex1 = "Java(?=8|11|17)";//Java Java Java Java
//?! 获取不匹配`regex`的文本的前面部分,不包括`regex`
String regex3 = "Java(?!8|11|17)";//Java
Pattern p = Pattern.compile(regex1);
Matcher matcher = p.matcher(str);
while (matcher.find()){
System.out.print(matcher.group()+" ");
}