正则表达式(Regex)指南
date
Jul 15, 2022
slug
正则表达式
status
Published
tags
正则表达式
杂项
summary
type
Post
从入门到精通:一份全面的正则表达式(Regex)指南
在编程和文本处理的世界里,正则表达式(Regular Expression,常缩写为 Regex 或 Regexp)是一个无比强大的工具。它能帮你从海量文本中,精准地查找、匹配和替换符合特定模式的字符串。无论你是前端开发者需要验证用户输入,还是后端工程师需要解析日志文件,掌握 Regex 都将让你事半功倍。
这篇指南将带你从最基础的概念开始,逐步深入到高级技巧,彻底掌握这个“文本瑞士军刀”。
什么是正则表达式?
简单来说,正则表达式是一组由字母、数字和特殊符号组成的“规则字符串”,它定义了你想要查找的文本模式。
它是一种从左到右匹配目标字符串的模式。想象一下,你想为一个应用设定用户名规则:必须包含小写字母、数字、下划线和连字符,并且长度在3到15个字符之间。
使用正则表达式,我们可以这样定义这个规则:
^[a-z0-9_-]{3,15}$我们来拆解一下这个例子:
^:开始标记,表示匹配必须从字符串的开头开始。
[a-z0-9_-]:字符集,表示允许的字符包括:所有小写字母(a-z)、所有数字(0-9)、下划线(_)和连字符(-)。
{3,15}:量词,表示前面的字符集必须连续出现3到15次。
$:结束标记,表示匹配必须在字符串的结尾结束。
根据这个规则,
john_doe 和 john12-as 是合法的,但 Jo 就不合法,因为它包含了大写字母且长度太短。1. 基本匹配
正则表达式最简单的形式就是直接匹配。它由一些字母和数字组合而成,会精确匹配一模一样的字符串。
- 示例:正则表达式
the
- 匹配:
The fat cat sat on **the** mat.
- 注意:基本匹配是大小写敏感的。因此,
The不会匹配the。
2. 核心利器:元字符
元字符是 Regex 的精髓,它们不代表字面意思,而是有特殊的含义。
2.1 点运算符 .
点
. 是最简单的元字符,它能匹配除换行符外的任意单个字符。- 示例:
c.t
- 匹配:
The fat **cat** sat on the mat.
2.2 字符集 []
方括号
[] 用来定义一个字符集,表示匹配方括号内任意一个字符。- 示例:
[Tt]he
- 匹配:
*The** car is parked in **the** garage.
否定字符集
[^]:如果在方括号内的开头使用 ^,则表示匹配除了方括号内字符以外的任意字符。- 示例:
[^c]ar
- 匹配:
The car parked in the ga**rar**ge.(匹配了rar,但跳过了car)
2.3 重复次数(量词)
量词用来指定一个字符或字符组需要重复出现的次数。
符号 | 描述 | 示例 | 匹配 |
* | 匹配0次或多次 | \\s*cat\\s* | The fat** cat **sat on the concatenation. |
+ | 匹配1次或多次 | c.+t | The fat **cat sat on the mat**. |
? | 匹配0次或1次(表示可选) | [T]?he | **The** car is parked in **the** garage. |
{n,m} | 匹配最少n次,最多m次 | [0-9]{2,3} | The number was 9.9997 but we rounded it off to **10**. |
{n} | 精确匹配n次 | [0-9]{3} | The number was 9.**999**7 but we rounded it off to 10.0. |
2.4 特征标群 ()
括号
() 用于将多个字符组合成一个单元(一个子模式)。量词可以作用于这个单元。- 示例:
(ab)*
- 说明:匹配连续出现的 "ab" 零次或多次。
2.5 或运算符 |
竖线
| 的作用是“或”,用于匹配 | 左边或右边的表达式。- 示例:
(T|t)he|car
- 匹配:
*The** **car** is parked in **the** garage.
2.6 转义特殊字符 \\
如果你想匹配元字符本身(如
.、*、?),需要在其前面加上反斜杠 \\ 进行转义。- 示例:
(f|c|m)at\\.?
- 匹配:
The fat **cat** sat on the **mat.**
2.7 锚点 ^ 和 $
锚点用于将匹配锁定在字符串的特定位置。
^:匹配字符串的开头。
$:匹配字符串的结尾。
- 示例:
^(T|t)he匹配以The或the开头的字符串。
- 示例:
at\\.$匹配以at.结尾的字符串。
3. 简写字符集
为了方便,Regex 提供了一些常用字符集的简写形式。
简写 | 等同于 | 描述 |
\\w | [a-zA-Z0-9_] | 匹配字母、数字或下划线(单词字符) |
\\W | [^\\w] | 匹配非单词字符 |
\\d | [0-9] | 匹配任意数字 |
\\D | [^\\d] | 匹配任意非数字字符 |
\\s | [\\t\\n\\f\\r ] | 匹配任意空白字符(空格、制表符、换行符等) |
\\S | [^\\s] | 匹配任意非空白字符 |
. | ㅤ | 匹配除换行符外的所有字符 |
4. 高级技巧:零宽度断言
零宽度断言(Lookarounds)是一种强大的高级技巧。它们用于检查某个位置之前或之后是否符合特定模式,但这个模式本身不会被包含在最终的匹配结果中。它们只起到断言(判断)的作用,不消耗任何字符。
符号 | 类型 | 描述 |
(?=...) | 正先行断言 (Positive Lookahead) | 要求当前位置的后面能匹配 ... 模式 |
(?!...) | 负先行断言 (Negative Lookahead) | 要求当前位置的后面不能匹配 ... 模式 |
(?<=...) | 正后发断言 (Positive Lookbehind) | 要求当前位置的前面能匹配 ... 模式 |
(?<!...) | 负后发断言 (Negative Lookbehind) | 要求当前位置的前面不能匹配 ... 模式 |
- 正先行断言示例:
(T|t)he(?=\\sfat) - 匹配:
*The** fat cat sat on the mat.(只匹配 "The",因为它后面跟着 " fat")
- 负先行断言示例:
(T|t)he(?!\\sfat) - 匹配:
The fat cat sat on **the** mat.(只匹配第二个 "the",因为它后面没有跟着 " fat")
- 正后发断言示例:
(?<=(T|t)he\\s)(fat|mat) - 匹配:
The **fat** cat sat on the mat.(只匹配 "fat",因为它前面是 "The ")
- 负后发断言示例:
(?<!(T|t)he\\s)cat - 匹配:
The cat sat on **cat**.(只匹配第二个 "cat",因为它前面没有 "The " 或 "the ")
5. 模式的“开关”:标志
标志(Flags)也叫修饰符,可以改变整个正则表达式的搜索行为。
标志 | 名称 | 描述 |
i | Case Insensitive | 忽略大小写进行匹配 |
g | Global Search | 全局搜索,查找所有匹配项,而不是找到第一个就停止 |
m | Multiline | 多行模式。使 ^ 和 $ 能匹配每一行的开头和结尾,而不仅仅是整个字符串的开头和结尾 |
- 示例:
/the/gi - 说明:
g表示全局搜索,i表示忽略大小写。 - 匹配:
*The** fat cat sat on **the** mat.(匹配所有 "the",不分大小写)
6. 贪婪与惰性匹配
默认情况下,量词(如
* 和 +)是贪婪的(Greedy),它们会尽可能多地匹配字符。- 贪婪示例:
/(.*at)/
- 匹配:
The fat cat sat on the mat.-> 匹配结果是*The fat cat sat on the mat**
有时我们希望它尽可能少地匹配。这时,可以在量词后面加上一个
?,使其变为惰性的(Lazy)。- 惰性示例:
/(.*?at)/
- 匹配:
The fat cat sat on the mat.-> 匹配结果是*The fat**(匹配到第一个at就停止了)
结语
正则表达式初看起来可能像一堆天书般的符号,但一旦理解了其核心组件——元字符、量词、锚点和标志——就会发现它是一个逻辑严谨且功能强大的工具。
掌握 Regex 的最好方法就是不断练习。利用在线的 Regex 测试工具(如 regex101.com),尝试构建和测试自己的模式,很快就能运用自如,解决各种复杂的文本处理难题。