正则表达式: 从基础到进阶的语法指南
正则表达式语法详解
- 前言
- 一、基础概念
- 二、基础元字符
- 2.1 字符匹配
- 2.2 字符类
- 2.3 预定义字符类
- 三、重复匹配
- 3.1 贪婪与非贪婪匹配
- 3.2 精确重复匹配
- 四、边界匹配
- 4.1 行首与行尾匹配
- 4.2 单词边界匹配
- 五、分组与引用
- 5.1 分组
- 5.2 反向引用
- 5.3 命名分组
- 六、逻辑运算符
- 6.1 或运算
- 七、正则表达式在不同语言中的应用
- 7.1 Python 中的正则表达式
- 7.2 Java 中的正则表达式
- 7.3 JavaScript 中的正则表达式
- 总结
前言
在编程和文本处理领域,正则表达式是一种描述文本模式的强大工具。无论是验证用户输入、提取文本信息,还是替换特定字符串,正则表达式都能高效完成任务。掌握正则表达式的语法,能让开发者在处理文本数据时如虎添翼。本文我将从基础语法入手,逐步深入到进阶用法,结合丰富的代码示例,带你全面掌握正则表达式的核心语法。
一、基础概念
正则表达式(Regular Expression,简称 Regex 或 RE)是一种由字符和特殊符号组成的模式,用于匹配、查找和操作文本。它通过定义一系列规则,能够快速定位符合特定模式的字符串。在 Java、Python、JavaScript 等编程语言,以及文本编辑器(如 Sublime Text、VS Code)中,都广泛支持正则表达式。
二、基础元字符
2.1 字符匹配
普通字符:普通字符直接匹配自身。例如,正则表达式abc
会匹配字符串中出现的abc
子串。
import re
text = "abc123"
result = re.search("abc", text)
print(result.group()) # 输出:abc
转义字符:当需要匹配一些具有特殊含义的字符(如.
、*
、+
等)时,需要使用反斜杠\
进行转义。例如,正则表达式\.
匹配字符.
。
text = "example.com"
result = re.search("\.", text)
print(result.group()) # 输出:.
2.2 字符类
字符类用方括号[]
表示,用于匹配括号内的任意一个字符。
单个字符:[abc]
匹配a
、b
或c
中的任意一个字符。
text = "banana"
result = re.findall("[abc]", text)
print(result) # 输出:['a', 'a', 'a']
字符范围:[a-z]
匹配任意小写字母,[0-9]
匹配任意数字。
text = "abc123def"
result = re.findall("[0-9]", text)
print(result) # 输出:['1', '2', '3']
取反字符类:[^abc]
匹配除a
、b
、c
之外的任意字符。
text = "abcdef"
result = re.findall("[^abc]", text)
print(result) # 输出:['d', 'e', 'f']
2.3 预定义字符类
元字符 | 含义 | 示例 |
---|---|---|
. | 匹配除换行符\n 之外的任意字符 | a.c 匹配abc 、a0c 等 |
\d | 匹配任意数字,等价于[0-9] | \d+ 匹配连续的数字串 |
\D | 匹配任意非数字字符,等价于[^0-9] | \D+ 匹配连续的非数字字符 |
\s | 匹配空白字符(空格、制表符、换行符等),等价于[ \t\n\r\f\v] | \s+ 匹配连续的空白字符 |
\S | 匹配非空白字符,等价于[^ \t\n\r\f\v] | \S+ 匹配连续的非空白字符 |
\w | 匹配字母、数字或下划线,等价于[a-zA-Z0-9_] | \w+ 匹配连续的单词字符 |
\W | 匹配非字母、数字或下划线的字符,等价于[^a-zA-Z0-9_] | \W+ 匹配连续的非单词字符 |
text = "Hello 123 World!"
result1 = re.findall("\d", text)
result2 = re.findall("\s", text)
print(result1) # 输出:['1', '2', '3']
print(result2) # 输出:[' ', ' ']
三、重复匹配
3.1 贪婪与非贪婪匹配
*
:匹配前面的字符或字符类零次或多次(贪婪匹配,尽可能多地匹配)。例如,a*
匹配零个或多个a
。
text = "aaaaab"
result = re.search("a*b", text)
print(result.group()) # 输出:aaaaab
+
:匹配前面的字符或字符类一次或多次。例如,a+
至少匹配一个a
。
text = "aaaaab"
result = re.search("a+b", text)
print(result.group()) # 输出:aaaaab
?
:匹配前面的字符或字符类零次或一次。例如,a?b
匹配b
或ab
。
text1 = "b"
text2 = "ab"
result1 = re.search("a?b", text1)
result2 = re.search("a?b", text2)
print(result1.group()) # 输出:b
print(result2.group()) # 输出:ab
非贪婪匹配:在重复匹配符后加上?
,使其变为非贪婪模式,尽可能少地匹配。例如,<.*?>
(贪婪)与<.*?>
(非贪婪)在匹配 HTML 标签时的区别:
html = "<div>content1</div><div>content2</div>"
greedy_result = re.search("<.*>", html)
non_greedy_result = re.search("<.*?>", html)
print(greedy_result.group()) # 输出:<div>content1</div><div>content2</div>
print(non_greedy_result.group()) # 输出:<div>content1</div>
3.2 精确重复匹配
{n}
:匹配前面的字符或字符类恰好n
次。例如,a{3}
匹配连续的三个a
。
text = "aaab"
result = re.search("a{3}b", text)
print(result.group()) # 输出:aaab
{n,}
:匹配前面的字符或字符类至少n
次。例如,a{2,}
匹配至少两个连续的a
。
text = "aaaa"
result = re.search("a{2,}", text)
print(result.group()) # 输出:aaaa
{n,m}
:匹配前面的字符或字符类至少n
次,最多m
次。例如,a{1,3}
匹配一到三个连续的a
。
text1 = "a"
text2 = "aa"
text3 = "aaa"
result1 = re.search("a{1,3}", text1)
result2 = re.search("a{1,3}", text2)
result3 = re.search("a{1,3}", text3)
print(result1.group()) # 输出:a
print(result2.group()) # 输出:aa
print(result3.group()) # 输出:aaa
四、边界匹配
4.1 行首与行尾匹配
^
:匹配字符串的开头。例如,^abc
匹配以abc
开头的字符串。
text1 = "abcdef"
text2 = "defabc"
result1 = re.search("^abc", text1)
result2 = re.search("^abc", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
$
:匹配字符串的结尾。例如,abc$
匹配以abc
结尾的字符串。
text1 = "defabc"
text2 = "abcdef"
result1 = re.search("abc$", text1)
result2 = re.search("abc$", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
4.2 单词边界匹配
\b
:匹配单词边界(单词与非单词字符之间的位置)。例如,\bcat\b
只匹配独立的单词cat
,而不匹配category
中的cat
。
text1 = "cat is cute"
text2 = "category"
result1 = re.search("\bcat\b", text1)
result2 = re.search("\bcat\b", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
\B
:匹配非单词边界。例如,\Bcat\B
匹配category
中的cat
,但不匹配独立的cat
。
text1 = "cat is cute"
text2 = "category"
result1 = re.search("\Bcat\B", text1)
result2 = re.search("\Bcat\B", text2)
print(result1 is not None) # 输出:False
print(result2 is not None) # 输出:True
五、分组与引用
5.1 分组
使用圆括号()
进行分组,分组后的内容可以被后续引用或单独处理。例如,(abc)
将abc
作为一个分组。
text = "abcabc"
result = re.search("(abc)\\1", text)
print(result.group()) # 输出:abcabc
5.2 反向引用
反向引用使用\n
(n
为分组的编号,从 1 开始)来引用前面的分组。例如,(\d{3})-(\d{4})
可以通过\1
和\2
分别引用两个分组的内容。
text = "123-4567"
result = re.search("(\d{3})-(\d{4})", text)
print(result.group(1)) # 输出:123
print(result.group(2)) # 输出:4567
5.3 命名分组
在 Python 3.6 + 中,可以使用(?P<name>pattern)
进行命名分组,通过(?P=name)
进行反向引用。
text = "123-4567"
result = re.search("(?P<area_code>\d{3})-(?P<phone_num>\d{4})", text)
print(result.group("area_code")) # 输出:123
print(result.group("phone_num")) # 输出:4567
六、逻辑运算符
6.1 或运算
使用|
表示或运算,匹配|
两边的任意一个模式。例如,(cat|dog)
匹配cat
或dog
。
text1 = "I have a cat"
text2 = "I have a dog"
result1 = re.search("(cat|dog)", text1)
result2 = re.search("(cat|dog)", text2)
print(result1.group()) # 输出:cat
print(result2.group()) # 输出:dog
七、正则表达式在不同语言中的应用
7.1 Python 中的正则表达式
Python 通过re
模块支持正则表达式,常用方法包括re.search()
(查找第一个匹配项)、re.findall()
(查找所有匹配项)、re.sub()
(替换匹配项)等。
text = "hello 123 world 456"
new_text = re.sub("\d+", "xxx", text)
print(new_text) # 输出:hello xxx world xxx
7.2 Java 中的正则表达式
Java 通过java.util.regex
包支持正则表达式,使用Pattern
和Matcher
类进行操作。
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexExample {public static void main(String[] args) {String text = "hello 123 world 456";Pattern pattern = Pattern.compile("\\d+");Matcher matcher = pattern.matcher(text);String newText = matcher.replaceAll("xxx");System.out.println(newText); // 输出:hello xxx world xxx}
}
7.3 JavaScript 中的正则表达式
JavaScript 通过RegExp
对象和字符串的相关方法(如match()
、replace()
)支持正则表达式。
let text = "hello 123 world 456";
let newText = text.replace(/\d+/g, "xxx");
console.log(newText); // 输出:hello xxx world xxx
总结
正则表达式的语法丰富且灵活,从基础的字符匹配到复杂的分组、反向引用和逻辑运算,每个部分都有其独特的用途。在实际应用中,需要根据具体需求选择合适的语法规则。通过不断练习和实践,才能熟练掌握正则表达式,在文本处理任务中发挥其强大的功能。
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ
相关文章:
正则表达式: 从基础到进阶的语法指南
正则表达式语法详解 前言一、基础概念二、基础元字符2.1 字符匹配2.2 字符类2.3 预定义字符类 三、重复匹配3.1 贪婪与非贪婪匹配3.2 精确重复匹配 四、边界匹配4.1 行首与行尾匹配4.2 单词边界匹配 五、分组与引用5.1 分组5.2 反向引用5.3 命名分组 六、逻辑运算符6.1 或运算 …...

uniapp|实现手机通讯录、首字母快捷导航功能、多端兼容(H5、微信小程序、APP)
基于uniapp实现带首字母快捷导航的通讯录功能,通过拼音转换库实现汉字姓名首字母提取与分类,结合uniapp的scroll-view组件与pageScrollTo API完成滚动定位交互,并引入uni-indexed-list插件优化索引栏性能。 目录 核心功能实现动态索引栏生成联系人列表渲染滚动定位联动性…...

【Linux】基础IO(二)
📝前言: 上篇文章我们对Linux的基础IO有了一定的了解,这篇文章我们来讲讲IO更底层的东西: 重定向及其原理感受file_operation文件缓冲区 🎬个人简介:努力学习ing 📋个人专栏:Linux…...
SpringBoot异步处理@Async深度解析:从基础到高阶实战
一、异步编程基础概念 1.1 同步 vs 异步 特性同步异步执行方式顺序执行,阻塞调用非阻塞,调用后立即返回线程使用单线程完成所有任务多线程并行处理响应性较差,需等待前任务完成较好,可立即响应新请求复杂度简单直观较复杂&#…...

【生存技能】ubuntu 24.04 如何pip install
目录 原因解决方案说明关于忽略系统路径 在接手一个新项目需要安装python库时弹出了以下提示: 原因 这个报错是因为在ubuntu中尝试直接使用 pip 安装 Python 包到系统环境中,ubuntu 系统 出于稳定性考虑禁止了这种操作 这里的kali是因为这台机器的用户起名叫kali…...

SHAP分析!Transformer-GRU组合模型SHAP分析,模型可解释不在发愁!
SHAP分析!Transformer-GRU组合模型SHAP分析,模型可解释不在发愁! 目录 SHAP分析!Transformer-GRU组合模型SHAP分析,模型可解释不在发愁!效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于SHAP分析…...
Tcp 通信简单demo思路
Server 端 -------------------------- 初始化部分 ------------------------------- 1.创建监听套接字: 使用socket(协议家族,套接字的类型,0) 套接字类型有 SOCK_STREAM:表示面向连接的套接字(Tcp协议)&…...
MySQL 8.0安装(压缩包方式)
MySQL 8.0安装(压缩包方式) 下载安装包并解压 下载 https://dev.mysql.com/downloads/mysql/可关注“后端码匠”回复“MySQL8”关键字获取 解压(我解压到D:\dev\mysql-8.4.5-winx64目录下) 创建mysql服务 注意,这步之前一定要保证自己电…...
常见标签语言的对比
XML、JSON 和 YAML 是常见的数据序列化格式 相同点 结构化数据表示 三者均支持嵌套结构,能描述复杂的数据层级关系(如对象、数组、键值对)。跨平台兼容性 均为纯文本格式,可被多种编程语言解析,适用于跨系统数据交换…...

知名人工智能AI培训公开课内训课程培训师培训老师专家咨询顾问唐兴通AI在金融零售制造业医药服务业创新实践应用
AI赋能未来工作:引爆效率与价值创造的实战营 AI驱动的工作革命:从效率提升到价值共创 培训时长: 本课程不仅是AI工具的操作指南,更是面向未来的工作方式升级罗盘。旨在帮助学员系统掌握AI(特别是生成式AI/大语言模型…...

Qt Creator 配置 Android 编译环境
Qt Creator 配置 Android 编译环境 环境配置流程下载JDK修改Qt Creator默认android配置文件修改sdk_definitions.json配置修改的内容 Qt Creator配置 异常处理删除提示占用编译报错连接安卓机调试APP闪退 环境 Qt Creator 版本 qtcreator-16.0.1Win10 嗯, Qt这个开发环境有点难…...

智能手表蓝牙 GATT 通讯协议文档
以下是一份适用于智能手表的 蓝牙 GATT 通讯协议文档,适用于 BLE 5.0 及以上标准,兼容 iOS / Android 平台: 智能手表蓝牙 GATT 通讯协议文档 文档版本:V1.0 编写日期:2025年xx月xx日 产品型号:Aurora Wat…...
AWS EC2源代码安装valkey命令行客户端
sudo yum -y install openssl-devel gcc wget https://github.com/valkey-io/valkey/archive/refs/tags/8.1.1.tar.gz tar xvzf 8.1.1.tar.gz cd valkey-8.1.1/ make distclean make valkey-cli BUILD_TLSyes参考 Connecting to nodes...

RT-THREAD RTC组件中Alarm功能驱动完善
使用Rt-Thread的目的为了更快的搭载工程,使用Rt-Thread丰富的组件和第三方包资源,解耦硬件,在更换芯片时可以移植应用层代码。你是要RTT的目的什么呢? 文章项目背景 以STM32L475RCT6为例 RTC使用的为LSE外部低速32 .756k Hz 的…...
MySQL解决主从复制的报错问题
MySQL 8.4 非 GTID 模式部分数据库主从复制指南 在进行MySQL 8.4非GTID模式下部分数据库主从复制时,以下是详细的操作步骤以及对应的执行位置说明,还有报错处理方法介绍: 操作步骤 1. 备份主库指定数据库(db1、db2)…...

用ffmpeg压缩视频参数建议
注意:代码中的斜杠\可以删除 一、基础压缩命令(画质优先) libx265推荐配置 ffmpeg -i input.mp4 -c:v libx265 -crf 25 -preset medium -c:a aac -b:a 128k output.mp4-crf:建议25-28(值越小画质越高) -preset:平…...

输入顶点坐标输出立方体长宽高的神经网络 Snipaste贴图软件安装
写一个神经网络,我输入立方体投影线段的三视图坐标,输出分类和长宽高 放这了明天接着搞 -------------------------------------------- 开搞 然而我的数据是这样的 winget install Snipaste f1启动,双击贴图隐藏 用右边4个数据做输入…...

用python清除PDF文件中的水印(Adobe Acrobat 无法删除)
学校老师发的资料,有时候会带水印,有点强迫症的都想给它去掉。用Adobe Acrobat试了下,检测不到水印,无法删除!分析发现原来这类PDF文件是用word编辑的,其中的水印是加在了页眉中! 自己动手想办法…...
kotlin 数据类
一 kotlin数据类与java普通类区别 Kotlin 的 data class 与 Java 中的普通类(POJO)相比,确实大大减少了样板代码(boilerplate),但它的优势不止于自动生成 getter/setter、copy()、equals()、toString()&am…...
豆瓣电影Top250数据工程实践:从爬虫到智能存储的技术演进(含完整代码)
目录 引言:当豆瓣榜单遇见大数据技术 项目文档 1.1 选题背景 1.2 项目目标 2. 项目概述 2.1 系统架构设计 2.2 技术选型 2.3 项目环境搭建 2.3.1 基础环境准备 2.3.2 爬虫环境配置 2.3.3 Docker安装ES连接Kibana 安装IK插件 2.3.4 vscode依赖服务安装 3. 核心模…...
把Excel数据文件导入到Oracle数据库
数据管理和分析的领域,将Excel中的数据导入到Oracle数据库是一个常见的需求,无论是为了利用Oracle强大的数据处理能力,还是为了实现数据的集中存储和管理,这一过程都需要一定的步骤和技巧,本文将详细介绍如何从Excel导…...
PyTorch API 6 - 编译、fft、fx、函数转换、调试、符号追踪
文章目录 torch.compiler延伸阅读 torch.fft快速傅里叶变换辅助函数 torch.func什么是可组合的函数变换?为什么需要可组合的函数变换?延伸阅读 torch.futurestorch.fx概述编写转换函数图结构快速入门图操作直接操作计算图使用 replace_pattern() 进行子图…...

Dagster Pipes系列-1:调用外部Python脚本
本文是"Dagster Pipes教程"的第一部分,介绍如何通过Dagster资产调用外部Python脚本并集成到数据管道中。首先,创建Dagster资产subprocess_asset,利用PipesSubprocessClient资源执行外部脚本external_code.py,实现跨进程…...

python shutil 指定文件夹打包文件为 zip 压缩包
python shutil 指定文件夹打包文件为 zip 压缩包,具体代码如下: import shutil# 指定要打包的文件夹路径 src_doc ./test# 指定输出的压缩包文件名(不包含扩展名) output_filename testfromat_ zip# 打包并压缩文件夹为 ZIP …...

Webug4.0通关笔记25- 第30关SSRF
目录 一、SSRF简介 1.SSRF原理 2.渗透方法 二、第30关SSRF渗透实战 1.打开靶场 2.渗透实战 (1)Windows靶场修复 (2)Docker靶场修复 (3)获取敏感文件信息 (4)内网端口与服务…...
Android学习总结之线程池篇
一、线程池参数调优实战真题 真题 1:直播 APP 弹幕加载线程池设计 题目描述:直播 APP 需要实时加载弹幕数据(网络请求,IO 密集型),同时渲染弹幕视图(UI 操作需切主线程)࿰…...

OpenCV 中用于背景分割的一个类cv::bgsegm::BackgroundSubtractorLSBP
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::bgsegm::BackgroundSubtractorLSBP 是 OpenCV 中用于背景分割的一个类,它基于局部样本二进制模式(Local Sample Bina…...

MacOS 上构建 gem5
MacOS 中只存在 python3,但是scons 只认 python,不在 系统中创建 软连接,一个是因为比较难操作;另一个是尽量不要更改系统。所以独立构件python 和scons: 1,安装python 下载源代码: Python S…...

认识中间件-以及两个简单的示例
认识中间件-以及两个简单的示例 什么是中间件一个响应处理中间件老朋友 nest g如何使用为某个module引入全局引入编写逻辑一个日志中间件nest g mi 生成引入思考代码进度什么是中间件 官方文档 中间件是在路由处理程序之前调用的函数。中间件函数可以访问请求和响应对象,以及…...

(五)毛子整洁架构(分布式日志/Redis缓存/OutBox Pattern)
文章目录 项目地址一、结构化日志1.1 使用Serilog1. 安装所需要的包2. 注册服务和配置3. 安装Seq服务 1.2 添加分布式id中间件1. 添加中间件2. 注册服务3. 修改Application的LoggingBehavior 二、Redis缓存2.1 添加缓存1. 创建接口ICaching接口2. 实现ICaching接口3. 注册Cachi…...