2024-05-13 17:18:47 +08:00
|
|
|
|
---
|
|
|
|
|
title: 正则表达式
|
|
|
|
|
description: 正则表达式基础入门
|
|
|
|
|
keywords:
|
|
|
|
|
- 正则表达式
|
|
|
|
|
tags:
|
2024-10-14 16:48:38 +08:00
|
|
|
|
- FormalSciences/ComputerScience
|
|
|
|
|
- GettingStarted/Other
|
2024-05-13 17:18:47 +08:00
|
|
|
|
author: 仲平
|
|
|
|
|
date: 2024-05-13
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
正则表达式(Regular Expression,Regex)是用于匹配字符串中字符组合的模式。它由一系列字符和特殊符号组成,可以高效地执行查找、替换、检查数据格式等多种文本处理任务。正则表达式的概念最初由数学家斯蒂芬·克莱尼在 20 世纪 50 年代提出,最早用于理论计算机科学和形式语言理论中。
|
|
|
|
|
|
|
|
|
|
几乎所有现代编程语言都支持正则表达式,包括 Python、JavaScript、Java、C#等。此外,许多文本编辑器和开发环境(如 VSCode、Sublime Text)以及命令行工具(如 grep)也广泛应用正则表达式进行文本搜索和编辑。
|
|
|
|
|
|
|
|
|
|
## 基本概念
|
|
|
|
|
|
|
|
|
|
- **字面字符**:指在表达式中表示它们自身字面意义的字符,例如 `a`、`1`、`B`。
|
|
|
|
|
- **特殊字符**:在正则表达式中用来表示控制或通配符作用的字符,如 `*`(匹配前一个字符 0 次或多次)。
|
|
|
|
|
|
|
|
|
|
### 元字符
|
|
|
|
|
|
|
|
|
|
元字符是构成正则表达式逻辑的基础,具有特殊的匹配含义:
|
|
|
|
|
|
|
|
|
|
| 元字符 | 描述 |
|
|
|
|
|
| ------- | ------------------------------------------------------------ |
|
|
|
|
|
| `.` | 句号匹配任意单个字符除了换行符。 |
|
|
|
|
|
| `[ ]` | 字符种类。匹配方括号内的任意字符。 |
|
|
|
|
|
| `[^ ]` | 否定的字符种类。匹配除了方括号里的任意字符 |
|
|
|
|
|
| `*` | 匹配 >=0 个重复的在 * 号之前的字符。 |
|
|
|
|
|
| `+` | 匹配 >=1 个重复的 + 号前的字符。 |
|
|
|
|
|
| `?` | 标记 ? 之前的字符为可选。 |
|
|
|
|
|
| `{n,m}` | 匹配 num 个大括号之前的字符或字符集 (n <= num <= m)。 |
|
|
|
|
|
| `(xyz)` | 字符集,匹配与 xyz 完全相等的字符串。 |
|
|
|
|
|
| `|` | 或运算符,匹配符号前或后的字符。 |
|
|
|
|
|
| `\` | 转义字符,用于匹配一些保留的字符 `[ ] ( ) { } . * + ? ^ $ \ |`。 |
|
|
|
|
|
| `^` | 从开始行开始匹配。 |
|
|
|
|
|
| `$` | 从末端开始匹配。 |
|
|
|
|
|
|
|
|
|
|
### 字符类
|
|
|
|
|
|
|
|
|
|
字符类允许匹配指定集合中的字符,常见的标准字符类和自定义字符类如下:
|
|
|
|
|
|
|
|
|
|
| 简写 | 描述 |
|
|
|
|
|
| ---- | -------------------------------------------------- |
|
|
|
|
|
| `.` | 除换行符外的所有字符 |
|
|
|
|
|
| `\w` | 匹配所有字母数字,等同于 `[a-zA-Z0-9_]` |
|
|
|
|
|
| `\W` | 匹配所有非字母数字,即符号,等同于: `[^\w]` |
|
|
|
|
|
| `\d` | 匹配数字: `[0-9]` |
|
|
|
|
|
| `\D` | 匹配非数字: `[^\d]` |
|
|
|
|
|
| `\s` | 匹配所有空格字符,等同于: `[\t\n\f\r\p{Z}]` |
|
|
|
|
|
| `\S` | 匹配所有非空格字符: `[^\s]` |
|
|
|
|
|
| `\f` | 匹配一个换页符 |
|
|
|
|
|
| `\n` | 匹配一个换行符 |
|
|
|
|
|
| `\r` | 匹配一个回车符 |
|
|
|
|
|
| `\t` | 匹配一个制表符 |
|
|
|
|
|
| `\v` | 匹配一个垂直制表符 |
|
|
|
|
|
| `\p` | 匹配 CR/LF(等同于 `\r\n`),用来匹配 DOS 行终止符 |
|
|
|
|
|
|
|
|
|
|
**自定义字符类**
|
|
|
|
|
|
|
|
|
|
| 示例 | 描述 |
|
|
|
|
|
| --------- | ----------------------------------------------- |
|
|
|
|
|
| `[a-z]` | 匹配任何小写字母 |
|
|
|
|
|
| `[A-Z]` | 匹配任何大写字母 |
|
|
|
|
|
| `[0-9]` | 匹配任何数字 |
|
|
|
|
|
| `[aeiou]` | 匹配所有小写元音字母 |
|
|
|
|
|
| `[^0-9]` | 匹配任何不是数字的字符(方括号内的 `^` 表示非) |
|
|
|
|
|
|
|
|
|
|
### 位置匹配
|
|
|
|
|
|
|
|
|
|
位置匹配用于确定字符匹配的具体位置,如行首或行尾等:
|
|
|
|
|
|
|
|
|
|
| 锚点字符 | 描述 |
|
|
|
|
|
| -------- | ------------------------------------------------------------ |
|
|
|
|
|
| `^` | 不仅表示行的开始,也可在多行模式中匹配每一行的开始 |
|
|
|
|
|
| `$` | 表示行的结束或字符串的结束,同样在多行模式中可匹配每一行的结束 |
|
|
|
|
|
|
|
|
|
|
## 量词和分组
|
|
|
|
|
|
|
|
|
|
量词和分组是正则表达式中非常强大的功能,它们让我们可以定义复杂的模式,进行精确的文本匹配和操作。这部分内容也可以用表格形式进行更清晰的展示。
|
|
|
|
|
|
|
|
|
|
### 量词
|
|
|
|
|
|
|
|
|
|
量词用于指定一个元素出现的次数,是正则表达式中控制匹配频度的关键工具。
|
|
|
|
|
|
|
|
|
|
| 量词 | 描述 |
|
|
|
|
|
| ------- | ------------------------------------ |
|
|
|
|
|
| `*` | 匹配前一个元素 0 次或多次。 |
|
|
|
|
|
| `+` | 匹配前一个元素 1 次或多次。 |
|
|
|
|
|
| `?` | 匹配前一个元素 0 次或 1 次。 |
|
|
|
|
|
| `{n}` | 匹配前一个元素恰好 n 次。 |
|
|
|
|
|
| `{n,}` | 匹配前一个元素至少 n 次。 |
|
|
|
|
|
| `{n,m}` | 匹配前一个元素至少 n 次,但不超过 m 次。 |
|
|
|
|
|
|
|
|
|
|
#### 贪婪与非贪婪量词
|
|
|
|
|
|
|
|
|
|
量词默认为贪婪模式,尽可能多地匹配字符。通过添加 `?` 后缀,量词变为非贪婪模式,尽可能少地匹配字符。
|
|
|
|
|
|
|
|
|
|
| 类型 | 示例 | 描述 |
|
|
|
|
|
| ---------- | ------- | ------------------------------------------------------- |
|
|
|
|
|
| 贪婪匹配 | `a.*b` | 在 `axxxbxxxb` 中匹配从第一个 `a` 到最后一个 `b` 的整段文本。 |
|
|
|
|
|
| 非贪婪匹配 | `a.*?b` | 在 `axxxbxxxb` 中匹配最短的,以 `a` 开始,以 `b` 结束的文本。 |
|
|
|
|
|
|
|
|
|
|
### 分组和引用
|
|
|
|
|
|
|
|
|
|
分组允许将正则表达式中的部分模式括起来,作为一个整体进行操作,这对于提取信息、构建复杂模式或进行条件匹配非常有用。
|
|
|
|
|
|
|
|
|
|
#### 捕获分组与非捕获分组
|
|
|
|
|
|
|
|
|
|
| 类型 | 示例 | 描述 |
|
|
|
|
|
| ---------- | --------- | ----------------------------------------------- |
|
|
|
|
|
| 捕获分组 | `(abc)` | 匹配 `abc`,并捕获匹配的文本,以供后续引用。 |
|
|
|
|
|
| 非捕获分组 | `(?:abc)` | 匹配 `abc`,但不捕获匹配的文本,仅用于匹配操作。 |
|
|
|
|
|
|
|
|
|
|
#### 后向引用
|
|
|
|
|
|
|
|
|
|
后向引用让我们能够引用正则表达式中先前定义的捕获组,这对于匹配重复的文本或验证两部分内容相同非常有用。
|
|
|
|
|
|
|
|
|
|
| 示例 | 描述 |
|
|
|
|
|
| -------------- | --------------------------------------------------------- |
|
|
|
|
|
| `(\b\w+)\s+\1` | 匹配一个由单词、空格和相同单词构成的模式,如 `word word`。 |
|
|
|
|
|
|
|
|
|
|
## 高级匹配
|
|
|
|
|
|
|
|
|
|
### 断言
|
|
|
|
|
|
|
|
|
|
断言是正则表达式中的一个高级特性,允许进行条件匹配,即只有在满足特定条件的情况下才进行匹配。
|
|
|
|
|
|
|
|
|
|
| 符号 | 描述 |
|
|
|
|
|
| ---- | --------------- |
|
|
|
|
|
| `?=` | 正先行断言 - 存在 |
|
|
|
|
|
| `?!` | 负先行断言 - 排除 |
|
|
|
|
|
| `?<=` | 正后发断言 - 存在 |
|
|
|
|
|
| `?<!` | 负后发断言 - 排除 |
|
|
|
|
|
|
|
|
|
|
**前向肯定断言** (`?=`)
|
|
|
|
|
|
|
|
|
|
- 前向肯定断言允许你指定一个子模式必须出现在某个匹配之后,但不会成为匹配结果的一部分。例如,`a(?=b)` 会匹配前面有 `a` 且后面紧跟 `b` 的位置,但不会返回 `b`。
|
|
|
|
|
|
|
|
|
|
**前向否定断言** (`?!`)
|
|
|
|
|
|
|
|
|
|
- 前向否定断言用来指定一个子模式必须不出现在某个匹配之后。例如,`a(?!b)` 会匹配所有后面不跟 `b` 的 `a`。
|
|
|
|
|
|
|
|
|
|
**后向断言**
|
|
|
|
|
|
|
|
|
|
- 在支持的语言中(如 JavaScript),后向断言允许你指定一个子模式必须出现在某个匹配之前。如 `(?<=b)a` 表示 `a` 前面必须有 `b`。
|
|
|
|
|
|
|
|
|
|
### 标志/模式修饰符
|
|
|
|
|
|
|
|
|
|
标志或模式修饰符用于改变正则表达式的匹配行为。
|
|
|
|
|
|
|
|
|
|
| 标志 | 描述 |
|
|
|
|
|
| ---- | ----------------------------------------------------- |
|
|
|
|
|
| `i` | 忽略大小写。 |
|
|
|
|
|
| `g` | 全局搜索。 |
|
|
|
|
|
| `m` | 多行修饰符:锚点元字符 `^` `$` 工作范围在每行的起始。 |
|
|
|
|
|
|
|
|
|
|
**大小写不敏感** (`i`)
|
|
|
|
|
|
|
|
|
|
- 使用此标志后,匹配时将不区分大小写。例如,正则表达式 `/abc/i` 将匹配 `Abc`、`aBc`、`abc` 等。
|
|
|
|
|
|
|
|
|
|
**多行模式** (`m`)
|
|
|
|
|
|
|
|
|
|
- 在多行模式下,`^` 和 `$` 不仅匹配输入字符串的开始和结束位置,也匹配行的开始和结束。
|
|
|
|
|
|
|
|
|
|
**点号包含换行** (`s`)
|
|
|
|
|
|
|
|
|
|
- 通常,`.` 不匹配换行符。使用此标志后,`.` 也将匹配换行符。
|
|
|
|
|
|
|
|
|
|
## 参考实例
|
|
|
|
|
|
|
|
|
|
- [regex101(正则表达式测试工具)](https://regex101.com/)
|
|
|
|
|
- [REGEXP(正则表达式测试工具)](https://regexr.com/)
|
|
|
|
|
- [Regulex(正则表达式可视化工具)](https://jex.im/regulex)
|
|
|
|
|
- [any-rule(正则表达式大全)](https://github.com/any86/any-rule)
|
|
|
|
|
- [learn-regex](https://github.com/ziishaned/learn-regex)
|