正则表达式入门
正则表达式入门: 正则表达式30分钟入门教程
正则表达式练习:https://regex101.com/
限定符
符号 | 含义 | 示例 |
---|---|---|
* |
出现0次或多次 | a* 匹配a 0次或多次 |
+ |
出现1次或多次 | a+ 匹配a 1次或多次 |
? |
出现0次或1次 | a? 匹配a或没有a |
{数字} |
出现指定次数 | a{6} 匹配a 6c次 |
{上界,下界} |
出现 \([上界,下界]\) 次 | a{2,6} 匹配a 2到6次 |
{上界,} |
出现 \([上界,下界)\) 次 | a{2,} 匹配a 2次及以上 |
或运算符
正则表达式中实际上只有或运算符,没有与和非运算符。
符号 | 含义 | 示例 |
---|---|---|
` | ` | 或 |
字符类
符号 | 含义 | 示例 |
---|---|---|
[范围] |
匹配范围指定的1个字符 | [a-fA-F0-9] 匹配大小写英文字母及数字 |
[[:alnum]] |
字母和数字 | |
[[:alpha:]] |
字母 | |
[[:ascii:]] |
ASCII编码0-127号字符 | |
[[:blank:]] |
空格或制表符 | |
[[:cntrl:]] |
控制符 | |
[[:digit:]] |
十进制数字 | |
[[:xdigit:]] |
十六进制数字 | |
[[:graph:]] |
可见字符(不含空白字符) | |
[:lower:] |
小写字母 | |
[[:print:]] |
可见字母 | |
[[:punct:]] |
可见标点字符 | |
[[:space:]] |
空白字符 | |
[[:upper:]] |
大写字母 | |
[[:word:]] |
单词字符 |
示例:
[abc] 匹配a或b或c
[a-c] 同上
[a-fA-F0-9] 匹配大小写英文字母及数字
[^0-9] 匹配非数字字符
元字符
符号 | 含义 | 示例 |
---|---|---|
\d |
匹配数字 | |
\D |
匹配非数字 | |
\w |
匹配单词字符(英文字母、数字、下划线) | |
\W |
匹配非单词字符 | |
\s |
匹配空白字符(包括换行、制表符) | |
\S |
匹配非空白字符 | |
. |
匹配任意字符(换行符除外) | |
\ |
转义(按文本形式处理字符) | |
\Q...\E |
引用,视为纯文本进行匹配 |
示例:
.* 匹配所有字符串
锚点
符号 | 含义 | 示例 |
---|---|---|
^ |
匹配行首 | |
` | 符号 | 含义 |
---- | ------------------------------------------------------- | ---- |
^ |
匹配行首 | |
匹配行尾 | ||
\b |
匹配单词边界(用于实现全字匹配,避免出现前导/后随字符) | |
\B |
匹配非单词边界 | |
\A |
匹配文本开头 | |
\z |
匹配文本最末尾 |
修饰符
符号 | 含义 | 示例 |
---|---|---|
g |
全局模式 | |
m |
多行模式 | |
i |
不区分大小写 | |
s |
单行模式 | |
U |
懒惰模式 |
贪婪/懒惰匹配
默认贪婪匹配,表示在有多个匹配可能的情况下,选择字符数最多的那个;末尾加 ?
表示改为懒惰匹配,表示在有多个匹配可能的情况下,选择字符数最少的那个。
示例:
<.+> 贪婪匹配任意字符
<.+?> 懒惰匹配任意字符
子表达式/捕获组
捕获组(capture groups):正则表达式中被 ()
标记的子表达式(sub-expression)。当正则匹配成功时,该组所匹配的内容会被单独捕获保存,方便后续对这部分匹配的内容进行提取、引用。
符号 | 含义 | 示例 |
---|---|---|
(?:...) |
捕获组 | |
(?:...) |
非捕获组 | |
(?P<name>...) |
命名捕获组 | |
\0 |
完整的匹配内容 | |
\从1开始的编号 或 $从1开始的编号 |
捕获组n的匹配内容 | |
${foo} |
命名捕获组foo的匹配内容 |
捕获组会按 括号的 “出现顺序” 自动编号,编号从 1
开始,而 整个正则表达式匹配的完整内容被默认为 “第 0 组”(不通过括号定义,是隐式的)。
对于嵌套的括号,编号按 “左括号” 出现的顺序计算:
(a(b(c)))
- 第 0 组:整个匹配结果(如
abc
); - 第 1 组:最外层括号
(a(b(c)))
匹配的内容(如abc
); - 第 2 组:中间括号
(b(c))
匹配的内容(如bc
); - 第 3 组:最内层括号
(c)
匹配的内容(如c
)。
捕获组的核心用途
捕获组的价值在于对“捕获的内容”进行复用或提取,主要有两种场景:
1. 反向引用(在正则表达式内部引用)
可以在正则表达式中用 \n
(n
是组编号)引用前面捕获组匹配的内容,实现“重复匹配相同子串”的效果。
示例 1:匹配重复的单词
\b(\w+)\s+\1\b
(\w+)
捕获一个单词(第 1 组);\1
引用第 1 组捕获的内容,\s+
匹配空格;- 整体匹配“重复的单词”(如
hello hello
、test test
)。
示例 2:匹配对称的 HTML 标签
<(\w+)>.*?</\1>
(\w+)
捕获标签名(如div
,第 1 组);\1
引用标签名,确保闭合标签与开始标签一致(如<div>...</div>
会匹配,<div>...</span>
不匹配)。
2. 提取数据(在正则表达式外部引用)
示例:从日期字符串中提取年、月、日
正则表达式:(\d{4})-(\d{2})-(\d{2})
对字符串 2023-10-05
匹配后:
- 第 0 组:
2023-10-05
(完整匹配); - 第 1 组:
2023
(年); - 第 2 组:
10
(月); - 第 3 组:
05
(日)。
在 Python 中提取的代码示例:
import re
match = re.match(r'(\d{4})-(\d{2})-(\d{2})', '2023-10-05')
print(match.group(0)) # 输出:2023-10-05(第0组)
print(match.group(1)) # 输出:2023(第1组)
print(match.group(2)) # 输出:10(第2组)
命名捕获组(Named Capturing Groups)
当正则表达式中捕获组较多时,用编号引用容易混淆,此时可以给捕获组命名,通过名称引用更直观。
语法:(?<name>pattern)
或 (?'name'pattern)
(不同语言可能略有差异,如 JavaScript 支持 (?<name>...)
)。
示例:命名捕获组提取日期
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
- 命名组
year
对应年,month
对应月,day
对应日。
在 Python 中通过名称提取:
match = re.match(r'(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})', '2023-10-05')
print(match.group('year')) # 输出:2023
print(match.group('month')) # 输出:10
非捕获组(Non-capturing Groups)
如果只需要用括号进行“分组匹配”(如结合 |
表示逻辑或),但不需要捕获内容,可以使用 非捕获组,语法:(?:pattern)
。
非捕获组不会被编号,也不会保存匹配内容,可减少内存消耗。
示例:匹配“http”或“https”
(?:http|https)://
(?:http|https)
是一个非捕获组,仅用于分组匹配“http”或“https”,但不会保存这部分内容。
综合示例
#[a-zA-F0-9]{6}\b 匹配RGB十六进制表示
^((25[0-5]|2[0-4]\d|[1-9]\d?|0)\.){3}(25[0-5]|2[0-4]\d|[1-9]\d?|0)$ 匹配IP地址