news 2026/4/23 13:00:11

关于正则表达式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
关于正则表达式

一、前言

正则表达式(Regular Expression,简称 Regex)是一种用于匹配、查找、替换字符串的强大工具,广泛应用于数据验证、日志分析、文本处理等场景。无论是前端表单验证、后端数据清洗,还是爬虫数据提取,正则表达式都能大幅提升开发效率。本文将避开复杂的理论推导,聚焦实用语法 + 场景化案例,帮助开发者快速掌握正则表达式的核心用法。

二、正则表达式基础语法

2.1 核心元字符(必记)

元字符

作用说明

示例

.

匹配任意单个字符(除换行符\n)

a.b 匹配 acb、aab,不匹配 abbc

*

匹配前面的字符 0 次或多次

ab* 匹配 a、ab、abb、abbb

+

匹配前面的字符 1 次或多次

ab+ 匹配 ab、abb,不匹配 a

?

匹配前面的字符 0 次或 1 次(非贪婪匹配)

ab? 匹配 a、ab,不匹配 abb

^

匹配字符串开头

^abc 匹配 abc123,不匹配 xabc

$

匹配字符串结尾

abc$ 匹配 123abc,不匹配 abcx

[]

字符集:匹配其中任意一个字符

[a-zA-Z] 匹配任意大小写字母

[^]

否定字符集:匹配不在其中的字符

[^0-9] 匹配非数字字符

()

分组:将多个字符视为一个整体,可捕获结果

(ab)+ 匹配 ab、abab

|

逻辑或:匹配左右任意一个表达式

a|b 匹配 a 或 b

\

转义字符:匹配元字符本身

a\.b 匹配 a.b,不匹配 acb

2.2 常用预定义字符集(简化书写)

预定义字符

等价写法

作用说明

\d

[0-9]

匹配数字

\D

[^0-9]

匹配非数字

\w

[a-zA-Z0-9_]

匹配字母、数字、下划线

\W

[^a-zA-Z0-9_]

匹配非字母、数字、下划线

\s

[ \t\n\r\f]

匹配空白字符(空格、制表符、换行符等)

\S

[^ \t\n\r\f]

匹配非空白字符

2.3 量词(指定匹配次数)

量词

作用说明

示例

{n}

匹配前面的字符恰好 n 次

a{3} 匹配 aaa,不匹配 aa

{n,}

匹配前面的字符至少 n 次

a{2,} 匹配 aa、aaa、aaaa

{n,m}

匹配前面的字符 n 到 m 次

a{2,3} 匹配 aa、aaa,不匹配 a

三、实战场景:正则表达式的核心应用

3.1 场景 1:数据验证(最常用)

数据验证是正则表达式的经典场景,如验证手机号、邮箱、身份证号等,确保输入数据格式合法。

3.1.1 验证手机号(中国大陆)
  • 规则:11 位数字,以 13/14/15/17/18/19 开头
  • 正则表达式:^1[345789]\d{9}$

Java 实现

import java.util.regex.Pattern;

import java.util.regex.Matcher;

public class RegexDemo {

// 手机号正则表达式

private static final String PHONE_REGEX = "^1[345789]\\d{9}$";

private static final Pattern PHONE_PATTERN = Pattern.compile(PHONE_REGEX);

public static boolean validatePhone(String phone) {

if (phone == null || phone.isEmpty()) {

return false;

}

Matcher matcher = PHONE_PATTERN.matcher(phone);

return matcher.matches();

}

public static void main(String[] args) {

System.out.println(validatePhone("13812345678")); // true

System.out.println(validatePhone("12345678901")); // false(开头不是13/14等)

System.out.println(validatePhone("1381234567")); // false(不足11位)

}

}

Python 实现

import re

def validate_phone(phone):

phone_regex = r"^1[345789]\d{9}$"

return re.fullmatch(phone_regex, phone) is not None

# 测试

print(validate_phone("13812345678")) # True

print(validate_phone("12345678901")) # False

print(validate_phone("1381234567")) # False

3.1.2 验证邮箱
  • 规则:用户名 @域名(用户名可包含字母、数字、下划线、点号;域名至少包含一个点)
  • 正则表达式:^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$

Python 实现

def validate_email(email):

email_regex = r"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"

return re.fullmatch(email_regex, email) is not None

print(validate_email("test123@qq.com")) # True

print(validate_email("test.name_123@gmail.com")) # True

print(validate_email("test@.com")) # False(域名格式错误)

3.2 场景 2:字符串提取(从文本中提取目标信息)

从复杂文本中提取指定格式的信息(如提取日志中的 IP 地址、提取字符串中的数字)。

3.2.1 提取文本中的所有 IP 地址(IPv4)
  • IPv4 规则:4 组 0-255 的数字,以点号分隔(需处理 0-255 的范围限制)
  • 正则表达式:\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

Java 实现

public class RegexExtract {

private static final String IP_REGEX = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b";

private static final Pattern IP_PATTERN = Pattern.compile(IP_REGEX);

public static List> extractIp(String text) {

List ips = new ArrayList

Matcher matcher = IP_PATTERN.matcher(text);

while (matcher.find()) { // 循环查找所有匹配的IP

ips.add(matcher.group());

}

return ips;

}

public static void main(String[] args) {

String log = "用户登录日志:IP=192.168.1.1,时间=2024-05-20;IP=255.255.255.255,时间=2024-05-21;无效IP=256.0.0.1";

ListIp(log);

System.out.println(ips); // 输出:[192.168.1.1, 255.255.255.255]

}

}

3.2.2 提取字符串中的所有数字(包括整数和小数)
  • 正则表达式:-?\d+(?:\.\d+)?(-?匹配负号,\d+匹配整数部分,(?:\.\d+)?匹配小数部分)

Python 实现

def extract_numbers(text):

number_regex = r"-?\d+(?:\.\d+)?"

return re.findall(number_regex, text)

text = "商品价格:99元,折扣价:89.9元,库存:-10(缺货),折扣率:0.85"

numbers = extract_numbers(text)

print(numbers) # 输出:['99', '89.9', '-10', '0.85']

3.3 场景 3:字符串替换(批量修改文本)

批量替换文本中的指定内容(如替换特殊字符、格式化日期、脱敏手机号)。

3.3.1 手机号脱敏(中间 4 位替换为 *)
  • 需求:将手机号13812345678替换为138****5678
  • 正则表达式:(\d{3})\d{4}(\d{4})(分组捕获前 3 位和后 4 位)

Java 实现

public class RegexReplace {

public static String maskPhone(String phone) {

String phoneRegex = "(\\d{3})\\d{4}(\\d{4})";

// 替换为:$1****$2($1表示第一个分组,$2表示第二个分组)

return phone.replaceAll(phoneRegex, "$1****$2");

}

public static void main(String[] args) {

System.out.println(maskPhone("13812345678")); // 输出:138****5678

}

}

3.3.2 清除文本中的所有空白字符
  • 正则表达式:\s+(匹配一个或多个空白字符)

Python 实现

def remove_whitespace(text):

return re.sub(r"\s+", "", text)

text = " 正则表达式 实战 指南 \n 2024-05-20 "

result = remove_whitespace(text)

print(result) # 输出:正则表达式实战指南2024-05-20

四、进阶技巧:提升正则表达式效率

4.1 分组与捕获
  • 捕获组:用()包裹的表达式会被捕获,可通过$n(Java)或\n(Python)引用捕获结果(如 3.3.1 中的手机号脱敏);
  • 非捕获组:用(?:)包裹的表达式仅用于分组,不捕获结果,可提升性能(如 IP 提取中的(?:25[0-5]...))。
4.2 贪婪匹配与非贪婪匹配
  • 贪婪匹配(默认):尽可能匹配更多字符(如a.*b匹配aabbaab中的aabbaab);
  • 非贪婪匹配:在量词后加?,尽可能匹配更少字符(如a.*?b匹配aabbaab中的aab和aab)。

示例(Python)

text = "aaabbbccc"

# 贪婪匹配:.* 匹配所有字符,直到最后一个c

greedy = re.findall(r"a.*c", text)

print(greedy) # 输出:['aaabbbccc']

# 非贪婪匹配:.*? 匹配到第一个c为止

non_greedy = re.findall(r"a.*?c", text)

print(non_greedy) # 输出:['aaabbbccc']?不,实际输出:['aaabbbccc']?不对,修正示例:

text = "aaacbbbc"

greedy = re.findall(r"a.*c", text) # 匹配整个字符串:['aaacbbbc']

non_greedy = re.findall(r"a.*?c", text) # 匹配到第一个c:['aaac']

4.3 正向预查与反向预查(零宽断言)

零宽断言仅匹配位置,不消耗字符,常用于 “匹配某个字符前后的内容”。

断言类型

语法

作用说明

示例

正向先行断言

(?=exp)

匹配 exp 前面的位置

a(?=b) 匹配ab中的a,不匹配ac中的a

正向负向断言

(?!exp)

匹配不满足 exp 前面的位置

a(?!b) 匹配ac中的a,不匹配ab中的a

反向先行断言

(?<=exp)

匹配 exp 后面的位置

(? 匹配ab中的b,不匹配cb中的b`

反向负向断言

(?<!exp)

匹配不满足 exp 后面的位置

(?b 匹配cb中的b,不匹配ab中的b

示例:匹配密码中包含至少 1 个大写字母、1 个小写字母和 1 个数字

  • 正则表达式:^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,16}$
  • 解析:
    • (?=.*[A-Z]):确保字符串中存在大写字母;
    • (?=.*[a-z]):确保存在小写字母;
    • (?=.*\d):确保存在数字;
    • .{8,16}:匹配 8-16 位任意字符。

五、避坑指南

  1. 转义字符问题:Java 中\需要双重转义(如\d需写为\\d),Python 中直接写\d即可;
  1. 性能问题:复杂正则表达式(如嵌套量词.*.*)可能导致回溯爆炸,尽量简化表达式(如用\d+代替\d*\d);
  1. 边界匹配:验证全字符串时务必加^和$(如手机号验证,否则138123456789会被误判为合法);
  1. 范围匹配:[0-9a-zA-Z]不能写成[a-z0-9A-Z](顺序不影响),但[a-Z]是错误的(大写字母 ASCII 码小于小写字母)。

六、常用工具推荐

  1. 在线正则表达式测试工具:Regex101(支持语法高亮、匹配结果实时预览,可选择语言);
  1. 正则表达式生成器:Regex Generator(输入示例文本,自动生成正则表达式);
  1. IDE 集成工具:IntelliJ IDEA、VS Code 均内置正则表达式测试功能(快捷键 Ctrl+F,开启 Regex 模式)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 17:54:29

探索STM32低成本MD500E永磁同步电机单电阻FOC无感算法

单电阻foc版本STM32低成本MD500E永磁同步pmsm&#xff0c;单电阻foc&#xff0c;无感算法方案&#xff0c;高性价比变频器方案 md500e单电阻采样&#xff1a;精简移植了md500e的无感svc部分到f103中&#xff0c;值得研究学习包括精简md500e移植到f103里的代 码一份 &#xff0c…

作者头像 李华
网站建设 2026/4/23 17:50:37

LSDYNA材料本构经验笔记:一座材料模型的宝库

lsdyna材料本构经验笔记&#xff0c;有500多页&#xff0c;包含各类金属土壤泡沫玻璃混凝土岩石等各种材料模型。最近研读了一本超有料的 “宝典”——500 多页的 LSDYNA 材料本构经验笔记&#xff0c;简直打开了新世界的大门。这笔记涵盖之广&#xff0c;从各类金属到土壤&…

作者头像 李华
网站建设 2026/4/23 14:52:21

信创云渲染:构建数字化未来的核心基石

在数字化转型不断深化的今天&#xff0c;渲染能力作为图形图像处理与三维可视化呈现的关键环节&#xff0c;其重要性日益凸显。特别是在信息技术应用创新产业蓬勃发展的背景下&#xff0c;满足国产化、安全可控要求的渲染解决方案&#xff0c;成为众多行业升级的迫切需求。传统…

作者头像 李华
网站建设 2026/4/23 18:03:50

丝杆支撑座同轴度如何安装?

丝杆支撑座的同轴度是保障传动系统平稳运行的关键&#xff0c;被广泛应用于数控机床、自动化设备、3D打印机等高精度传动系统。如偏心安装会导致丝杆弯曲、振动加剧甚至设备停机。如何在安装环节将同轴度误差控制在微米级&#xff1f;采用基准轴与百分表打表法&#xff1a;将一…

作者头像 李华
网站建设 2026/4/23 16:12:06

金融风控图 Agent 实时分析实战(99.9%准确率架构曝光)

第一章&#xff1a;金融风控图 Agent 的实时分析在高频交易与复杂欺诈手段并存的现代金融环境中&#xff0c;传统批处理式风控系统已难以应对毫秒级的风险识别需求。金融风控图 Agent 通过构建动态知识图谱&#xff0c;结合流式计算引擎&#xff0c;实现对账户、交易、设备等多…

作者头像 李华
网站建设 2026/4/23 14:35:25

【农业无人机路径规划终极指南】:揭秘高效率农田作业背后的智能算法

第一章&#xff1a;农业无人机路径规划的核心挑战在现代农业智能化进程中&#xff0c;无人机被广泛应用于作物监测、精准喷洒和播种等任务。然而&#xff0c;实现高效、安全的飞行作业依赖于科学合理的路径规划&#xff0c;这一过程面临多重技术与环境挑战。复杂地形适应性 农田…

作者头像 李华