Java Class:
Pattern
andMatcher
Noting!
find()
在输入字符串中查找与 正则表达式 匹配的子序列
. (此方法可以多次调用, 以查找输入字符串中的多个匹配子序列)
group()
返回整个
匹配的子串.group(0)
与group()
方法等价. (在正则表达式中, 组号是从 1 开始计数的, 因此Matcher.group(0)
不是用来获取第 0 组匹配的子串, 而是用来获取整个匹配的子串)
Matcher#matches()
将整个输入字符串
与 正则表达式 进行匹配. (此方法只会匹配一次, 只会匹配整体, 如果匹配失败, 则不能再调用此方法)
如果只使用matches()
方法, 可以直接调用String#matches
, 能省略中间部分代码
0 Java 正则匹配
String regex = "20\\d\\d";
System.out.println("2019".matches(regex)); // true
.
any 正则表达式a.c中间的.可以匹配一个任意字符且仅限一个字符(不包括0个)
\\d
number \\D
no number
\\$
匹配特殊字符 $
,正则表达式有特殊字符,那就需要用 \
转义,因为 \
也是Java字符串的转义字符,两个\\
实际上表示的是一个\
&
不是特殊字符
1 基础
- 双斜杠
\\
Java 中正则表达式中则需要有两个反斜杠 \\
才能被解析为其他语言中的转义作用
序列 \\\\
匹配 \\
,\\(
匹配 (
. \\
表示将下一字符标记为特殊字符、文本、反向引用 或 八进制转义符
根据 Java Language Specification 的要求,Java 源代码的字符串中的反斜线被解释为 Unicode 转义或其他字符转义。因此必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被 Java 字节码编译器解释。例如,当解释为正则表达式时,字符串字面值 “\b
” 与单个退格字符匹配,而 “\\b
” 与单词边界匹配。字符串字面值 “\(hello\)
” 是非法的,将导致编译时错误;要与字符串 “hello
” 匹配,必须使用字符串字面值 “\\(hello\\)
”。
- ^表示开头,$表示结尾
// 1. 使用括号()来进行分组匹配
Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
Matcher m = p.matcher("010-12345678");
// 2. 只看是否完全包含的情况 (只匹配一次)
if (m.matches()) {
String g1 = m.group(1);
String g2 = m.group(2);
}
// 3. 引擎会把匹配到的字符串去掉,方便下次一匹配(find()),这里是重置
m.reset();
while(m.find()){
String group = m.group(); // equal m.group(0); 获取当前匹配的子串
group.soutv;
}
// 4. 从开始的位置查找
m.lookingAt();
// 5. 只看是否包含子串的情况 (只匹配一次)
if(m.find()){
m.start() + "-" + m.end() // 当前匹配的子串的 开始位置, 结束位置
}
1.1 特殊字符
特殊字符很重要, 特别是在 java 中 regex 字符串有两层转义的情况.
必需在表示正则表达式的字符串文字中使用双重反斜杠,以保护它们免受Java字节码编译器的解释
反斜杠可以在非字母字符之前使用,无论该字符是否是未转义构造的一部分
\
将下一字符标记为特殊字符、文本、反向引用或八进制转义符
所有能转义的符号 \ ^ $ * + ? { . ( ) [
都是特殊字符
e.g. $
和 {
是; 而普通字母 d
和 w
不是
Pattern.compile("\\"); // 2 literal: "\" 匹配: ERROR 因为在正则里面单个 \ 代表"转义字符" 后面必须接字符, 哪怕是空格 ("\\ " 代表 空格, idea会提示不需要转义:"redundant escape")
Pattern.compile("\\\\"); // 4 literal: "\\" 匹配: "\" 这时 \ 后面没有接转义字符, \\ -> \
Pattern.compile("\\\\\\$\\\\\\{"); // 6 literal: "\\\$\\\{" 匹配: "\$\{" 这时 \ 后面接了转义字符
Pattern.compile("\\\$\\{"); // 3 & 2 literal: "\$\{" 匹配: "${"
- 为什么
$
需要3个{
只需 2个呢?
因为 $
代表结尾符号, 只用一个 $
就行, 而 \$
会在Java层面转义为 $
, 在加上前面的 \\
才是 正则里面的 \$
, 字面意义的 $
- 为什么 4 个
\\\\
才代表 regex 中的一个\
字面字符呢
Java 字节码编译器会自动解释, 所有字符串中的转义字符, 如 \n
. 实际虚拟机拿到的字符, 总是转义后的, 然后在正则中还需要表示转义字符, 就只有套娃了
不知道
\
属于哪个部分?
在idea中, 双击\
就行了
1.2 转义字符
\\w
word \\W
no words 等价与 [A-Za-z0-9_]
\s
匹配一个空格字符或tab字符
- 用于重复匹配的修饰符:
?
可以匹配0个或一个字符+
可以匹配至少一个字符{n}
精确指定n个字符。{n,}代表没有上限*
可以匹配任意个字符
# 范围由小到大
? 0~1
+ 1~n
{n} n个
* 任意个 0~n
# 在 aop 中
* 一层 任意字符
.. 多层 任意参数(0-多个参数)
- 括号: 捕获组 (group)
特殊组group(0) 总是代表整个表达式
- 普通捕获组
(1)(2(3)(4))
- 命名捕获组
(?<name>pattern)
(命名的捕获组同样也可以使用编号获取相应值)
e.g.(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<date>\\d{2}))
- 非捕获组
(?:pattern)
在左括号后紧跟 ?:,而后再加上正则表达式,构成非捕获组 (?:Expression)。
(?=pattern)
和(?!pattern)
也是非捕获匹配
1.3 非捕获元 ?=、?!、?<=、?<!
- 先行断言(lookahead)
exp1(?=exp2)
:查找exp2
前面的exp1
- 后行断言(lookbehind)
(?<=exp2)exp1
:查找exp2
后面的exp1
- 先行断言(lookahead)
exp1(?!exp2)
:查找后面不是exp2
的exp1
- 后行断言(lookbehind)
(?<!exp2)exp1
:查找前面不是exp2
的exp1
先行断言(lookahead) 和后行断言(lookbehind)它们只匹配某些位置,在匹配过程中,不占用字符,所以被称为"零宽"。
1.4 反向引用
content=Pattern.compile("(.)\\1+").matcher(content).replace("$1");
2 非贪婪匹配
正则表达式默认使用贪婪匹配:任何一个规则,它总是尽可能多地向后匹配,在规则后面加个?即可表示非贪婪匹配(注意使用括号括起来,如 (\d+?)(0*) )
(\d??)(9*) 匹配 “9999”,因为使用了非贪婪,所以第一组匹配了“”空字符串,注意\d?表示匹配0个或1个数字,后面第二个?表示非贪婪匹配
String.split()方法传入的正是正则表达式
String.replaceAll(),它的第一个参数是正则表达式,第二个参数是待替换的字符串。传入的第二个参数可以使用$1、$2来反向引用匹配到的子串(必须使用括号分组)
3 实例
判断是否包含大小写字母,数字和特殊字符
String regexZST = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$";
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
4 驼峰转下划线 正则
可以在 idea 等搜索框中便捷的使用
正则之驼峰转下划线
记住: upper case, lower case, end
序号 | 符号 | 含义 |
---|---|---|
1 | \l | 下个字符小写 |
2 | \u | 下个字符大写 |
3 | \L | 接着的字符均小写直到 \E |
4 | \U | 接着的字符均大写直到 \E |
5 | \E | 结束 \L, \E 和 \Q |
6 | \Q | 在转义字符前加上 \Q, 如 \Q$ |
1. 概要
- 小写
\l
代表接下来的 1 个字符 - 大写
\L
代表后面 所有 字符 - 使其小写 Lower
\L
- 使其大写 Upper
\U
- 控制结束 End
\E
$1对应的是正则中第一个元组(\d{3})匹配到的结果, $0代表匹配到的整个字符
2. 使用
开启正则匹配模式
- 将
_([a-z])
替换成\U$1\E
, 可以完成下划线转驼峰 - 将
List<(.*?)>
替换成$1
, 完成去掉外层 - 将
([A-Z])
替换成\L$1\E
大写 -> 小写 - 将
([a-z])
替换成\U$1\E
小写 -> 大写