正则表达式
Regular Expressions Regex
一、基本语法
1. 基础匹配
.
全部匹配[abc]
字符集[^abc]
否定字符集[a-z]
字母范围:我们需要将起始字母和结束字母写进[]
中,中间用连字符 - 分隔[0-9]
数字范围:我们需要将起始数字和结束数字写进[]
中,中间用连字符 - 分隔
2. 标志 Flags
unknown
/ Regex /g global
/ Regex /m multiline
/ Regex /i case insensitive
- global :默认只匹配第一个匹配项,全局标志使表达式选中所有匹配项
- multiline:默认将所有文本看作一行,多行标志可以单独处理每一行
- case insensitive:使我们编写的表达式不再大小写敏感,不区分大小写
3. 重复匹配 Repetitions
- 星号
*
Asterisk: 我们在字符后面加上*
,表示一个字符完全不匹配或可以匹配多次。 - 加号
+
The Plus: 为了表示一个字符可以出现一次或多次,我们将+
放在它后面 - 问号
?
The Question Mark:为了表示一个字符是可选的,我们在它后面加一个?
大括号 {}
Curly Braces :在该字符的末尾
- 为表示一个字符出现的确切次数,将它出现的次数写进大括号
{}
中,如{n}
- 为表示一个字符至少出现多少次,将它至少应出现的次数写进大括号
{}
中,并在数字后面加上逗号,
,如{n, }
- 为表示一些字符出现的次数在某个数字范围内,将它至少和至多出现的次数写进大括号
{}
中,中间用逗号,
分隔,如{x,y}
unknown
[0-9]{2,} //匹配文本中,位数至少为 2 的阿拉伯数字
4. 分组 Grouping
括号 ()
分组,我们可以对一个表达式进行分组,并用这些分组来引用或执行一些规则。为了给表达式分组,我们需要将文本包裹在 ()
中。 -\n
表示第 n 个分组
括号 (?:group)
非捕获分组:对表达式进行分组,但是不被引用捕获
unknown
(ha)-\1,(haa)-\2 \\ ha-ha,haa-haa
(?:ha)-ha,(haa)-\1 \\ ha-ha,haa-haa
5. 特殊
- 竖线
|
竖线允许一个表达式包含多个不同的分支。所有分支用 | 分隔。 (相当于或) - 转义字符
\
Escape Character:{} [] / \ + * . $ ^ | ?
这些特殊字符。为了匹配这些特殊字符本身,我们需要通过 \ 将它们转义 - 插入符
^
:匹配字符串的开始,在表达式前面加上^
- 美元符号
$
:匹配字符串的结束,在表达式末尾加上$
unknown
^[0-9] // 仅查找行首的数字
html$ // 在行末出现的 html
6. 预定义字符
简写 | 含义 | 等价于 |
---|---|---|
\d |
数字 | [0-9] |
\D |
非数字 | [^0-9] |
\w |
单词字符(字母、数字、下划线) | [A-Za-z0-9_] |
\W |
非单词字符 | [^A-Za-z0-9_] |
\s |
空白字符(空格、制表符、换行等) | [\t\n\r\f\v] |
\S |
非空白字符 | [^\t\n\r\f\v] |
7. 零宽断言 Lookarounds
希望正在写的词语出现在另一个词语之前或之后
lookahead 先行断言
- 正向先行断言 Positive lookahead:在表达式后面使用
(?=pattern)
,匹配出现在 pattern 前面的表达式 - 负向先行断言 Negative lookahead:在表达式后面使用
(?!pattern)
,不匹配出现在 pattern 前面的表达式
unknown
Date: 4 Aug 3PM
\d+(?=PM) // 得到 3
\d+(?!PM) // 得到 4
lookbehind 后行断言
- 正向后行断言 Positive lookbehind :在表达式前面使用正向后行断言
(?<=pattern)
,匹配出现在 pattern 后面的表达式 - 负向后行断言 Negative lookbehind assertion:在表达式前面使用
(?<!pattern)
,不匹配出现在 pattern 后面的表达式
unknown
Product Code: 1064 Price: $5
(?<=\$)\d+ //5 正向后行断言 匹配前面带有 $ 的数字
(?<!\$)\d+ //1064 负向后行断言
8. 匹配 Matching
- Greedy Matching : 正则表达式默认执行贪婪匹配。这意味着匹配内容会尽可能长
- Lazy Matching:在第一次匹配时停止,在
*
之后添加?
二、Python 使用
python
import re
API | 作用 | 返回值 |
---|---|---|
re.search(pattern, text) |
在任意位置找第一次匹配 | Match 对象或 None |
re.match(pattern, text) |
只在开头匹配 | Match 对象或 None |
re.fullmatch(pattern, text) |
整段必须完全匹配 | Match 对象或 None |
re.findall(pattern, text) |
返回所有匹配片段的列表 List | list[str] |
re.finditer(pattern, text) |
返回迭代器(省内存) | Iterator[Match] |
re.sub(pattern, repl, text, count=0) |
替换 | 替换后的字符串 |
实际使用
unknown
[\u4e00-\u9fa5] 匹配中文文本
实际例子:
正则表达式实现 Obsidian 路径批量更新
参考资料
交互式学习网站:https://regexlearn.com/