正则(regex)
正则语法
量词(Quantifiers)
在正则表达式中,* 和 + 都是量词(Quantifiers),它们决定了前面的字符或分组可以重复出现的次数。
它们的核心区别在于:“是否允许出现 0 次”。
| 符号 | 名称 | 匹配次数 | 是否必选 | 含义 |
|---|---|---|---|---|
* | 星号 (Asterisk) | 0 次或多次 | 可选 | 前面的内容可有可无,有的话可以有很多个。 |
+ | 加号 (Plus) | 1 次或多次 | 必选 | 前面的内容至少要出现一次,也可以有很多个。 |
如果想限制具体的次数,可以使用大括号:
{n}:正好出现n次。{n,}:至少出现n次。{n,m}:出现n到m次。
此外,?跟在前面的字符后代表可有可无。
等价符号
| . | 匹配除换行符(\n、\r)之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像"(.|\n)"的模式。 |
|---|---|
| \d | 匹配一个数字字符。等价于 [0-9]。 |
| \D | 匹配一个非数字字符。等价于 [ ^0-9]。 |
| \w | 匹配一个字母、数字、下划线。等价于[A-Za-z0-9_]。 |
| \W | 匹配非(字母、数字、下划线)。等价于 [ ^A-Za-z0-9_]。 |
| \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
| \S | 匹配任何非空白字符。等价于 [ ^ \f\n\r\t\v]。 |
| \n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
| \r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
| \t | 匹配一个制表符。等价于 \x09 和 \cI。 |
贪婪匹配与懒惰匹配
简单来说,**贪婪匹配(Greedy)和懒惰匹配(Lazy/Non-greedy)**的区别在于:面对多个可能的匹配结果时,是“能拿多少拿多少”还是“够了就行”。在正则表达式中,这两种模式直接影响你抓取数据的范围。
1. 贪婪匹配 (Greedy)
这是正则表达式的默认模式。
- 行为: 匹配器会尽可能多地吞掉字符,直到不符合条件为止。
- 常用符号:
*(0或多个)、+(1或多个)、{n,}。 - 例子: 假设我们要匹配
<div>内容1</div><div>内容2</div>中的 HTML 标签。- 正则:
<div>.*</div> - 匹配结果:
<div>内容1</div><div>内容2</div> - 解析: 它没有在第一个
</div>停止,而是直接匹配到了文档的最后一个</div>。
- 正则:
2. 懒惰匹配 (Lazy / Non-greedy)
- 行为: 匹配器在满足条件的前提下,尽可能少地匹配字符。一旦找到匹配项,立即停止。
- 实现方式: 在贪婪量词后面加一个问号
?。 - 常用符号:
*?、+?、??、{n,}?。 - 例子: 同样的 HTML 字符串。
- 正则:
<div>.*?</div> - 匹配结果:
<div>内容1</div>(以及接下来的<div>内容2</div>) - 解析: 碰到第一个符合条件的
</div>它就“收手”了。
- 正则:
核心区别对比
| 特性 | 贪婪匹配 (Greedy) | 懒惰匹配 (Lazy) |
|---|---|---|
| 性格 | 贪心,全都要 | 知足,够了就好 |
| 匹配长度 | 匹配最长的字符串 | 匹配最短的字符串 |
| 控制符 | *, +, {n,} | *?, +?, {n,}? |
| 回溯机制 | 从后往前找(先吞下全部再吐出来) | 从前往后找(吃一点看一点) |
举个直观的例子
字符串:"apple" "banana" "cherry"
- 贪婪模式
".*":匹配结果是整个字符串"apple" "banana" "cherry"。它认为最开头的"和最末尾的"才是这一对。 - 懒惰模式
".*?":匹配结果是三个独立的项:"apple"、"banana"和"cherry"。
特殊字符
**^:**匹配搜索字符串开始的位置。 如果标志中包括 m(多行搜索)字符,^ 还将匹配 \n 或 \r 后面的位置。
**$:**匹配搜索字符串结尾的位置。 如果标志中包括 m(多行搜索)字符,^ 还将匹配 \n 或 \r 前面的位置。
正则表达式 ^.{2,100}$ 匹配的是 任意长度在 2 到 100 个字符之间的字符串。