平时用得少,遇到就得到处找。这里总结一下用法,方便复查
1. 正则表达式(regular expression)
描述了字符串的模式匹配,可用于检索、替换、截取符合模式(规则)的串
预习内容:
- 需正则引擎来进行处理,通常该引擎嵌入程序中(Java正则包嵌到RT里面)
- 正则会首先返回第一个匹配的串,即使后面还有匹配的模式(急切性)
- 某些特殊字符需预处理才能传递给引擎( ,*,?),匹配特殊字符要用
转义
- 匹配
要用
\
,Java匹配路径用到正则,那么地址写法有两种:C:\dir\xxx.txt
C:/dir/xxx.txt
- Windows路径用
,Linux用
/
,为了跨平台性推荐使用/
来写路径
- 换行符(n)、回车符(r),二者区别类似上世纪打字机,不同系统对换行有不同要求:
- Windows:
rn
- Linux:
n
- Max:
r
- Windows:
2. 正则的组成
- 普通字符
- 字母 abcABC
- 数字 0123
- 标点符号 , . ?
- 其他符号
- 特殊字符(元字符)
- 非打印字符 r n
- 限定符 * ?
- 定位符 ^ $
- 选择 ( )
- 反向引用
2.1 非打印字符
字符 | 描述 |
---|---|
. | 除换行符 n之外的任意单字符 |
| | 或 |
n | 换行符 |
t | 回车符 |
d | 数字(digit) |
D | 除了数字 |
w | 单词(word),数字,大小写字母,下划线 |
W | 非单词 |
s | 空白符(空格,制表符,换页符等) |
S | 非空白符 |
2.2 限定符
字符 | 描述 |
---|---|
* | 0或多次 |
| 1或多次 |
? | 0或一次 |
{n} | 出现几次 |
{n, } | 至少几次 |
{n,m} | 出现n~m次 |
2.3 定位符
字符 | 描述 |
---|---|
^ | 开始 |
$ | 结束 |
b | 单词边界(字与空格间的位置) |
B | 非单词边界 |
2.4 选择
字符 | 描述 |
---|---|
() | 标记子表达式 |
补充:
- 字符集
[]
仅仅匹配里面的其中的一个 - [^] 表示取反,即不在字符集里面的内容,
[^0-9]
,表示不匹配数字
3. 正则优先级
正则表达式从左到右进行计算,并遵循优先级顺序,下表优先级从高到低
运算符 | 描述 |
---|---|
转义符 | |
()、[] | 圆括号、方括号 |
*、 、?、 {n,m} | 限定符 |
^、$、num | 定位符、分组编号 |
| | 替换 |
4. 匹配模式
修饰符 | 描述 |
---|---|
i | ignore:大小写不敏感 |
g | global:全局匹配 |
m | multiline:多行匹配,^$会匹配新行符 |
s | single:单行匹配,.会匹配新行符 |
5. 选择 ()
5.1 分组
可将括号内容看成一个整体进行匹配
代码语言:javascript复制(abc ),表示:abc出现1或多次
5.2 分支
使用分支时要用括号包裹
代码语言:javascript复制a(b | c | d),表示:ab、ac、ad的其中一个
5.3 分组引用
代码语言:javascript复制字符串:2020-11-07
模式串:(d{4})-(d{2})-(d{2})
不需要分组引用:(?:d{4})-(d{2})-(d{2}),引用需要缓存降低了速度
引用会把匹配到的组按编号存入缓存,0编号表示整体,后面依次是匹配的内容,使用n来访问分组:
- 0:2020-11-07
- 1:2020
- 2:11
- 3:07
6. 贪婪和惰性
贪婪是尽可能匹配多的字符,而惰性则是尽可能匹配少的字符(后面加 ? 实现惰性)
6.1 引擎工作原理
代码语言:javascript复制字符串:<h1>This is H1</h1>
贪婪模式串:<. >
惰性模式串:<. ?>
模式串中:<
匹配该字符,.
匹配任意非换行字符,
匹配1或多次前置字符直到换行,>
匹配该字符,?
表示惰性
贪婪流程:
<
匹配字符串的第一个<
.
一直匹配前面所有字符,直到最后的换行匹配失败- 然后引擎对下一个正则符号匹配,即匹配
>
,这时会进行回溯,即</h1>的>会被匹配到即立刻急切返回
惰性流程:
<
匹配字符串的第一个<
.
匹配h,因为是惰性,所以匹配了.
就开启匹配>
,尽可能返回少的字符- 而
>
匹配1失败,就会进行后移
,用.
继续匹配后面的1,然后重复上面一步 - 最终返回
<h1>
7. 正负向预查
- xxx(?=pattern):捕获xxx,而xxx是以xxxpattern结尾
- xxx(?!pattern):上面的否定,即不以pattern结尾
- (?<=pattern)xxx:捕获xxx,而xxx是以pattern开头
- (?<!pattern)xxx:上面的否定,即不以pattern开头
8. Java里的正则使用
java.util.regex 包主要包括以下三个类:
- Pattern:正则表达式的编译表示,不可变类能多线程使用
- Pattern.compile(reg,flag):表示匹配模式
- Matcher:是对输入字符串进行解释和匹配操作的引擎
- PatternSyntaxException:是一个非强制异常类,它表示一个正则表达式模式中的语法错误
8.1 匹配查找
代码语言:javascript复制public static void main(String[] args) throws InterruptedException {
String str = "123456789"; // 字符串
String reg = "\d "; // 模式串
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(str);
boolean b = matcher.matches(); // true
}
8.2 捕获组
代码语言:javascript复制public static void main(String[] args) throws InterruptedException {
String str = "020-123456"; // 字符串
String reg = "(\d{3})-(\d{6})"; // 模式串
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(str);
if(matcher.find()){
System.out.println(matcher.group(0)); // 020-123456
System.out.println(matcher.group(1)); // 020
System.out.println(matcher.group(2)); // 123456
}
}
8.3 替换
代码语言:javascript复制public static void main(String[] args) throws InterruptedException {
String str = "The dog is mine which dog is playing"; // 字符串
String reg = "dog"; // 模式串
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(str);
String strNew = matcher.replaceAll("cat");
System.out.println(strNew); // "The cat is mine which cat is playing"
}
8.4 String类的正则
代码语言:javascript复制public static void main(String[] args) throws InterruptedException {
String str = "123456789"; // 字符串
String reg = "\d "; // 模式串
boolean matches = str.matches(reg);
System.out.println(matches); // true
}
参考:
菜鸟教程
摩诘