1. 正则表达式的基本概念
正则表达式(Regex)是一种用于描述字符串模式的工具,通过特定语法匹配、查找、替换或验证文本。它由普通字符(如字母、数字)和特殊字符(元字符)组成,广泛应用于编程语言、文本处理工具(如 grep、sed)和框架(如 Spring Cloud Gateway)中。
核心用途
- 查找:在文本中匹配符合特定规则的字符串(如邮箱、手机号)。
- 替换:将匹配的文本替换为其他内容。
- 验证:检查输入是否符合预期格式(如表单验证)。
- 提取:从复杂文本中提取关键信息(如日志分析)。
2. 正则表达式的基本语法
(1) 元字符
元字符 | 说明 | 示例 |
---|---|---|
. |
匹配任意单个字符(除换行符外) | a.c 匹配 abc 、a1c |
\d |
匹配数字字符(等价于 [0-9] ) |
\d{3} 匹配 123 |
\D |
匹配非数字字符 | \D+ 匹配 abc |
\w |
匹配字母、数字或下划线(等价于 [a-zA-Z0-9_] ) |
\w+ 匹配 hello_123 |
\W |
匹配非字母、数字或下划线 | \W+ 匹配 !@# |
\s |
匹配空白字符(空格、制表符等) | \s+ 匹配多个空格 |
\S |
匹配非空白字符 | \S+ 匹配连续的非空字符 |
(2) 量词
量词 | 说明 | 示例 |
---|---|---|
* |
匹配前一个字符 0 次或多次 | a* 匹配 "" 、a 、aa |
+ |
匹配前一个字符 1 次或多次 | a+ 匹配 a 、aa ,但不匹配 "" |
? |
匹配前一个字符 0 次或 1 次 | a? 匹配 "" 或 a |
{n} |
匹配前一个字符 恰好 n 次 | a{3} 匹配 aaa |
{n,} |
匹配前一个字符 至少 n 次 | a{2,} 匹配 aa 、aaa |
{n,m} |
匹配前一个字符 至少 n 次,最多 m 次 | a{2,4} 匹配 aa 、aaa 、aaaa |
(3) 边界符号
符号 | 说明 | 示例 |
---|---|---|
^ |
匹配字符串的开头 | ^abc 匹配以 abc 开头的字符串 |
$ |
匹配字符串的结尾 | xyz$ 匹配以 xyz 结尾的字符串 |
\b |
匹配单词边界 | \bcat\b 匹配 cat ,但不匹配 category |
\B |
匹配非单词边界 | \Bcat\B 匹配 category 中的 cat |
(4) 字符类
[abc]
:匹配a
、b
或c
中的任意一个字符。[^abc]
:匹配 非 a、b、c 的字符。[a-z]
:匹配任意小写字母。[A-Z0-9]
:匹配任意大写字母或数字。
(5) 分组与捕获
- 捕获组:用
()
包裹的子表达式,可提取匹配内容。(\w+)-management(?<segment>/?.*)
(\w+)
:捕获模块名称(如storage
)。(?<segment>/?.*)
:捕获路径后缀(如/api/v1/data
)。
- 反向引用:通过
\1
、\2
等引用捕获组内容。(\w+)\s\1 # 匹配重复的单词(如 "hello hello")
3. 正则表达式在 Spring Cloud Gateway 中的应用
(1) 路径匹配与重写
在 Spring Cloud Gateway 的路由配置中,正则表达式常用于:
- 路径匹配:通过
Path
断言匹配请求路径。 - 路径重写:通过
RewritePath
过滤器修改请求路径。
(2) 示例:合并模块路径重写
需求:将 /xxx-management/**
请求统一转发到 mes-runtime
服务,并移除模块前缀(如 /storage-management/api
→ /api
)。
优化前(冗余配置):
filters:
- RewritePath=/storage-management(?<segment>/?.*), $\{segment}
- RewritePath=/carrier-management(?<segment>/?.*), $\{segment}
...
优化后(通用正则表达式):
filters:
- RewritePath=/(?<module>[a-zA-Z]+)-management(?<segment>/?.*), $\{segment}
- 解释:
(?<module>[a-zA-Z]+)
:捕获模块名称(如storage
、carrier
)。(?<segment>/?.*)
:捕获路径后缀(如/api/v1/data
)。$\{segment}
:替换为后缀部分,去除模块前缀。
(3) 注意事项
- 转义字符:在 YAML 中,反斜杠
\
需要转义为\\
。 - 测试工具:使用 regex101.com 验证正则表达式逻辑。
- 性能影响:复杂正则表达式可能增加匹配开销,需权衡简洁性与性能。
4. 高级用法:环视断言与非捕获组
(1) 环视断言(Lookaround)
- 正向前瞻:
(?=...)
,匹配某个位置 之后必须满足的条件。\d{3}(?=-) # 匹配后跟 `-` 的三位数字(如 `123-456` 中的 `123`)
- 正向后顾:
(?<=...)
,匹配某个位置 之前必须满足的条件。(?<=\d{3})-\d{3} # 匹配 `123-456` 中的 `-456`
- 负向前瞻/后顾:
(?!=...)
、(?<!...)
,匹配不满足条件的位置。
(2) 非捕获组
- 使用
(?:...)
定义分组,但不捕获内容。(?:storage|carrier)-management # 匹配 `storage-management` 或 `carrier-management`
5. 常见应用场景
(1) 表单验证
- 邮箱:
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
- 手机号(中国大陆):
^1[3-9]\d{9}$
- 日期(YYYY-MM-DD):
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$
(2) 日志分析
- 提取日志中的 IP 地址:
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
(3) 文本替换
- 将重复的单词替换为单次出现:
\b(\w+)\s+\1\b # 匹配 "hello hello" 替换为:$\1
6. 工具推荐
- 在线测试工具:
- regex101.com:实时验证正则表达式逻辑。
- RegExr:交互式学习与调试。
- 编程语言支持:
- Java:
java.util.regex.Pattern
。 - Python:
re
模块。 - JavaScript:正则表达式字面量
/pattern/
。
- Java:
7. 常见误区与避坑
- 贪婪匹配:
- 默认量词(如
*
、+
)是贪婪的,可能匹配过多内容。 - 使用
?
修饰为非贪婪模式:.*?
。
- 默认量词(如
- 转义字符:
- 特殊字符(如
.
、*
)需用\
转义。 - 在字符串中需双重转义(如
\\d
)。
- 特殊字符(如
- 边界条件:
- 使用
\b
匹配单词边界,避免部分匹配(如cat
vscategory
)。
- 使用
8. 总结
正则表达式是处理文本的强大工具,尤其在路径匹配、数据验证和文本提取场景中不可或缺。通过合理使用元字符、分组和断言,可以显著提升配置的简洁性与可维护性(如 Spring Cloud Gateway 的路由优化)。掌握其语法和高级用法,能有效解决复杂文本处理问题。