【文本处理】正则表达式

一、简介

正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。

二、起源

正则表达式的“鼻祖”或许可一直追溯到科学家对人类神经系统工作原理的早期研究。美国新泽西州的Warren McCulloch和出生在美国底特律的Walter Pitts这两位神经生理方面的科学家,研究出了一种用数学方式来描述神经网络的新方法,他们创造性地将神经系统中的神经元描述成了小而简单的自动控制元,从而作出了一项伟大的工作革新。

在1951 年,一位名叫Stephen Kleene的数学科学家,他在Warren McCulloch和Walter Pitts早期工作的基础之上,发表了一篇题目是《神经网事件的表示法》的论文,利用称之为正则集合的数学符号来描述此模型,引入了正则表达式的概念。正则表达式被作为用来描述其称之为“正则集的代数”的一种表达式,因而采用了“正则表达式”这个术语。

之后一段时间,人们发现可以将这一工作成果应用于其他方面。1968年,Unix之父Ken Thompson就把这一成果应用于计算搜索算法的一些早期研究。Ken Thompson将此符号系统引入编辑器QED,然后是Unix上的编辑器ed,并最终引入grep。Jeffrey Friedl 在其著作《Mastering Regular Expressions (2nd edition)》(中文版译作:精通正则表达式,已出到第三版)中对此作了进一步阐述讲解。

自此以后,正则表达式被广泛地应用到各种UNIX或类似于UNIX的工具中,如大家熟知的Perl。Perl的正则表达式源自于Henry Spencer编写的regex,之后已演化成了pcre(Perl兼容正则表达式Perl Compatible Regular Expressions),pcre是一个由Philip Hazel开发的、为很多现代工具所使用的库。正则表达式的第一个实用应用程序即为Unix中的 qed 编辑器。

三、引擎

正则引擎主要可以分为两大类:一种是确定型有穷自动机(Deterministic finite automaton, DFA),一种是非确定型有穷自动机(Non-deterministic finite automaton,NFA)。这两种引擎都有了很久的历史,当中也由这两种引擎产生了很多变体。于是POSIX的出台规避了不必要变体的继续产生。这样一来,主流的正则引擎又分为3类:一、DFA,二、传统型NFA,三、POSIX NFA。

   - **DFA引擎**:

DFA引擎对每一个字符只进行一次判断。它比较快速且其性能不受正则表达式复杂度的影响,但它不支持某些高级匹配特性,例如捕获组和回溯引用。
DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。

   - **NFA引擎**:

NFA引擎可以进行回溯,支持更复杂的正则功能,如前述的捕获组、非贪婪量词以及前后断言等。大部分现代编程语言使用这种引擎。然而,当正则表达式特别复杂时,NFA引擎可能导致性能下降,因为它会尝试所有可能的路径来匹配一个字符串。

传统的 NFA 引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。

POSIX NFA 引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎;并且在使用 POSIX NFA 时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。

使用DFA引擎的程序主要有:awk,egrep,flex,lex,MySQL,Procmail等;

使用传统型NFA引擎的程序主要有:GNU Emacs,Java,ergp,less,more,.NET语言,PCRE library,Perl,PHP,Python,Ruby,sed,vi;

使用POSIX NFA引擎的程序主要有:mawk,Mortice Kern Systems’ utilities,GNU Emacs(使用时可以明确指定);

也有使用DFA/NFA混合的引擎:GNU awk,GNU grep/egrep,Tcl。

举例简单说明NFA与DFA工作的区别:

比如有字符串this is yansen’s blog,正则表达式为 /ya(msen|nsen|nsem)/ (不要在乎表达式怎么样,这里只是为了说明引擎间的工作区别)。 NFA工作方式如下,先在字符串中查找 y 然后匹配其后是否为 a ,如果是 a 则继续,查找其后是否为 m 如果不是则匹配其后是否为 n (此时淘汰msen选择支)。然后继续看其后是否依次为 s,e,接着测试是否为 n ,是 n 则匹配成功,不是则测试是否为 m 。为什么是 m ?因为 NFA 工作方式是以正则表达式为标准,反复测试字符串,这样同样一个字符串有可能被反复测试了很多次。

而DFA则不是如此,DFA会从 this 中 t 开始依次查找 y,定位到 y ,已知其后为a,则查看表达式是否有 a ,此处正好有a 。然后字符串a 后为n ,DFA依次测试表达式,此时 msen 不符合要求淘汰。nsen 和 nsem 符合要求,然后DFA依次检查字符串,检测到sen 中的 n 时只有nsen 分支符合,则匹配成功。

由此可以看出来,两种引擎的工作方式完全不同,一个(NFA)以表达式为主导,一个(DFA)以文本为主导。一般而论,DFA引擎则搜索更快一些。但是NFA以表达式为主导,反而更容易操纵,因此一般程序员更偏爱NFA引擎。 两种引擎各有所长,而真正的引用则取决与你的需要以及所使用的语言。

四、实现正则表达式的库:

正则表达式的具体实现通常指具体编程语言或工具所使用的库或模块。例如:

   - **PCRE (Perl Compatible Regular Expressions)**:广泛用于各种语言和工具中,提供了类似Perl语言正则表达式功能的实现。
   - **std::regex**:C++的正则表达式库,可以在C++程序中使用。
   - **re**:这是Python语言中的一个标准库,用于提供正则表达式的支持。
   - **java.util.regex**:Java语言中用于处理正则表达式的类库。
   - **RegExp**:JavaScript中内建的正则表达式支持。

五、正则表达式的语法

正则表达式的语法可以非常复杂,但以下是一些基本的组成元素:

1. **字面量** (Literals):

任何非特殊字符都会匹配它自己。

2. **元字符** (Metacharacters):

在正则表达式中有特殊含义的字符,

如:
   - . 表示任何单个字符(除了换行符)。
   - ^ 表示行的开始。
   - $ 表示行的结束。
   - * 表示前一个字符的0次或多次匹配。
   - + 表示前一个字符的1次或多次匹配。
   - ? 表示前一个字符的0次或1次匹配。
   - {n,m} 表示前一个字符至少n次,不超过m次的匹配。

3. **字符集** (Character classes):

定义一个字符集合,匹配该集合中的任意字符。

   - [abc] 将匹配 "a"、"b" 或 "c"。
   - [^abc] 将匹配 "a"、"b" 和 "c" 之外的任何字符。
   - [a-z] 匹配任何小写字母。
   - [A-Z] 匹配任何大写字母。
   - [0-9] 匹配任何数字。

4. **转义字符** (Escape character): 

\ 被用来转义特殊字符。

   - \t 表示制表符。
   - \n 表示换行符。
   - \\ 表示字面量的反斜杠。
   - \. 表示字面量的点(不再是元字符了)。

5. **锚点** (Anchors):

 \b 和 \B 表示单词的边界和非边界。

   - \b 匹配一个单词边界,即字与空格间的位置。
   - \B 匹配非单词边界。

6. **分组** (Grouping) 和 **捕获** (Capturing):

   - 使用小括号`()`可以将多个字符组成一个单元,这个单元可以用`*+`等元字符来整体匹配。
   - (abc) 表示匹配字面字符串 "abc"。
   - (a|b) 表示匹配 "a" 或 "b"。

7. **非捕获分组** (Non-capturing groups):

使用`(?: ... )`可以进行分组但不捕获匹配的子字符串。

8. **前向和后向断言** (Lookahead and Lookbehind assertions):

   - 前向肯定断言 (?=...) 匹配一个后面跟着特定模式的位置。
   - 前向否定断言 (?!...) 匹配一个后面不跟着特定模式的位置。
   - 后向肯定断言 (?<=...) 匹配一个前面是特定模式的位置。
   - 后向否定断言 (?<!...) 匹配一个前面不是特定模式的位置。

正则表达式在各种编程语言中都有广泛的支持,包括Python、Java、JavaScript、C#、PHP等。在不同的编程语言中,正则表达式的工作方式和性能上可能有所差异,但基本的语法规则是一致的。在实际使用中,由于正则表达式的复杂性,通常推荐先通过文档加深理解,并在在线测试工具上练习,以便熟练掌握其强大的功能。 

六、正则表达式用例

1. **验证电子邮件地址**:

   ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

   - ^ 匹配输入字符串的开始位置。
   - [a-zA-Z0-9._%+-]+ 匹配前面的字符集合一次或多次(邮件用户名部分)。
   - @ 字面量字符 "@"。
   - [a-zA-Z0-9.-]+ 匹配邮件服务提供商名(域名前部)。
   - \. 字面量点,用来分隔域名的各部分。
   - [a-zA-Z]{2,} 匹配域名后缀(如.com、.org等),至少两个字符。
   - $ 匹配输入字符串的结束位置。

2. **匹配手机号码(以中国为例)**:

   ^1[3-9]\d{9}$

   - ^ 匹配输入字符串的开始位置。
   - 1 字面量数字 "1"。
   - [3-9] 匹配3到9之间的任一数字。(这假定手机号码第二位为3-9之间的数字)
   - \d{9} 匹配任意数字,连续9次。
   - $ 匹配输入字符串的结束位置。

3. **查找HTML标签**:

   <([a-z]+)([^<]+)*(?:>(.*)<\/\1>| *\/>)

   - < 开始的字面小于号。
   - ([a-z]+) 匹配并捕获一次或多次的小写字母(即标签名)。
   - ([^<]+)* 匹配除了小于号之外的任意字符,零次或多次。
   - (?: ... ) 是一个非捕获分组。
   - > 字面量大于号,结束标签的开始部分。
   - (.*) 匹配并捕获任意字符,零次或多次,直到闭标签前。
   - </\1> 中 \1 引用第一个捕获组,匹配相同的标签名。
   - | 表示或操作符,匹配前面或后面的表达式。
   - *\/> 匹配自闭合标签的结尾。

4. **匹配IPv4地址**:

   ^(\d{1,3}\.){3}\d{1,3}$

   - ^ 匹配输入字符串的开始位置。
   - (\d{1,3}\.){3} 单个数字字符重复1到3次,跟着点,这个模式重复3次(对应前三个数字及点)。
   - \d{1,3} 匹配1至3位数的数字字符。
   - $ 匹配输入字符串的结束位置。

5. **简单密码强度校验**:

   ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$

   - ^ 匹配输入字符串的开始位置。
   - (?=.*[A-Za-z]) 前向断言,确保至少存在一个字母。
   - (?=.*\d) 前向断言,确保至少存在一个数字。
   - [A-Za-z\d]{8,} 匹配8个或更多的字母或数字。
   - $ 匹配输入字符串的结束位置。

每个用例都是根据具体需求制定的,可能会因应用的上下文和要求不同而有所变化。在使用这些正则表达式时,需谨慎考虑边界情况和特定语言实现的细微差别,并应在实际环境中进行充分测试。

相关链接:

正则表达式_百度百科 (baidu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/577026.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

苹果发布了一个Ferret(雪貂)多模态大模型,在一个无人问津的角落被一位博主捞起来

苹果12月14日释放了一个名为Ferret的多模态大语言模型&#xff0c;有的翻译是雪貂&#xff0c;有的是法学硕士&#xff0c;要我说&#xff0c;还是叫雪貂吧&#xff0c;接地气亲民&#xff0c;将来犯蠢的时候出来发张雪貂的可爱表情包作公关就完事了&#xff0c;你个法学硕士到…

C语言—每日选择题—Day63

指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 设C语言中&#xff0c;一个int型数据在内存中占2个字节&#xff0c;则unsigned int型数据的取值范围为 A&#xff1a;0~255 B&#xff1a;0…

mysql8.x版本_select语句源码跟踪

总结 源码基于8.0.34版本分析&#xff0c;函数执行流程含义大致如下&#xff1a; do_command 方法从连接中读取命令并执行&#xff0c;调用 dispatch_command 对命令进行分发。dispatch_command 调用 mysql_parse 对命令进行解析&#xff0c;如果遇到一条语句用 ; 分隔多条命…

CGAL中三角形曲面网格近似

1、介绍 此软件包实现了变分形状近似&#xff08;VSA&#xff09;方法&#xff0c;通过更简单的表面三角形网格来近似输入表面网格。该算法的输入必须是&#xff1a; 三角形分割&#xff1b;组合2流形 输出是一个三角形汤&#xff0c;可以构建成多边形曲面网格。 给定一个输入曲…

linux操作系统——进程(二) 进程状态

进程状态 你真正的理解了进程的状态嘛?特别是操作系统教材中学过的进程状态&#xff0c;你真的理解了吗&#xff1f; 教材上关于进程状态的说明 下面我们以下图为例: 这是教材上对操作系统的说明&#xff0c;但是它并没有详细的说明&#xff0c;这些状态具体是什么&#xf…

大语言模型说明书

在浩瀚的信息宇宙中&#xff0c;大语言模型如同一颗璀璨的星星正在熠熠生辉。21世纪以来&#xff0c;人工智能可谓是飞速发展&#xff0c;从简单的神经网络到大语言模型、生成式AI&#xff0c;这并非仅仅是一种技术的进步&#xff0c;更是人类智慧的飞跃。大语言模型不仅仅是语…

华为数通方向HCIP-DataCom H12-831题库(多选题:241-249)

第241题 (NEW) 以下哪些操作可能会影响客户网络的正常运行? A、从设备上下载日志 B、软件升级 C、路由协议配置变更 D、debug核心交换机上转发的所有IP报文 答案:ABCD 解析: 第242题 对于防火墙的默认安全区 Trust 和 Untrust 的说法,正确的有 A、从 Trust 区域访问 Untr…

Vue在页面上添加水印

第一步&#xff1a;在自己的项目里创建一个js文件&#xff1b;如图所示我在在watermark文件中创建了一个名为waterMark.js文件。 waterMark.js /** 水印添加方法 */ let setWatermark (str1, str2) > {let id 1.23452384164.123412415if (document.getElementById(id) …

【MYSQL】MYSQL 的学习教程(六)之 SQL 语句执行流程

1. 一条 SQL 查询语句是如何被执行的 MySQL 的基本架构示意图如下所示&#xff1a; MYSQL 线程处理请求流程&#xff1a; SQL 接口&#xff1a;MySQL 中处理请求的线程在获取到请求以后获取 SQL 语句去交给 SQL 接口去处理查询解析器&#xff1a;解析器会将 SQL 接口传递过来…

操作系统期末复习知识点二计算与应用

1.理解银行家算法判断死锁的定理并能计算相关的参数。 2.能利用LRU、FIFO算法求缺页率。 3.纯页式管理中&#xff0c;求逻辑地址对应的物理地址&#xff0c;页号、页内地址长度&#xff0c;画出逻辑地址的格式&#xff0c;在引入块表时&#xff0c;求出有效访问时间。 4.可变分…

【Java】SpringBoot快速整合Kafka

目录 1.什么是Kafka&#xff1f; 主要特点和概念&#xff1a; 主要组成部分&#xff1a; 2.Kafka可以用来做什么&#xff1f; 3.SpringBoot整合Kafka步骤&#xff1a; 1. 添加依赖: 2. 配置 Kafka: 3. 创建 Kafka 生产者: 4. 创建 Kafka 消费者: 5. 发布消息: 6. 使…

【MySQL学习笔记007】约束

1、概述 &#xff08;1&#xff09;概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 &#xff08;2&#xff09;目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 &#xff08;3&#xff09;分类 约束 描述 关键字 …

【各种**问题系列】Java 数组集合之间的相互转换

&#x1f4cc; 问题点&#xff1a; 在 Coding 过程中经常会遇到数组、List、Set、Map 之间的相互转换......这里记录一下转换的几种方式。&#x1f636;&#x1f636;&#x1f636; 目录 &#x1f4cc; 集合转换 1.数组 转 List&#xff1a; 2.List 转 数组&#xff1a; 3…

如何将本地websocket发布至公网并实现远程访问服务端

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

AG16KDDF256 User Manual

AGM AG16KDDF256 是由 AGM FPGA AG16K 与 DDR-SDRAM 叠封集成的芯片&#xff0c;具有 AG16K FPGA的可编程功能&#xff0c;提供更多可编程 IO&#xff0c;同时内部连接大容量 DDR-SDRAM。  FPGA 外部管脚 FBGA256 封装&#xff0c;管脚说明请见下表 Table-1&#xff1a; Tab…

YUM和编译安装

一、安装Linux 1.编译安装&#xff0c;灵活性高&#xff0c;难度较大&#xff0c;可以安装较新的版本 2.rpm安装&#xff08;redhat&#xff09; linux包安装 rpm 软件名 3.yum yum是rpm升级版本&#xff0c;解决了rpm的弊端 2和3用的都是红帽打包好的软件包&#xff0c;能…

cad安装路径显示灰色选择不了怎么办?

cad安装路径显示灰色选择不了怎么办呢&#xff1f;今天教给大家。 灰色是因为之前下载过一次&#xff0c;没有删干净&#xff0c;注册表里还有cad&#xff0c;它认为你的电脑中有cad&#xff0c;所以安装路径是灰色的&#xff0c;不能安装。先同时按下【xinR】键&#xff0c;打…

ip addr和ifconfig

ip addr可以显示更多信息&#xff0c;包括为启动的网络驱动如wlan&#xff0c;而ifocnfig只显示在线的驱动。若wlan是down的&#xff0c;则ip addr会显示信息&#xff0c;ifconfig不会显示信息。 ip addr: ifconfig:

视频号视频怎么保存到手机相册?

在微信视频号中看到喜欢的视频&#xff0c;想要缓存下载到手机&#xff0c;却怎么也找不到办法。很多朋友会选择去录屏&#xff0c;但保存下来的视频实在是不美观&#xff0c;而且费时费力&#xff01;着实没必要&#xff01;下面给大家推荐一款亲测有效的微信视频号视频下载方…

【excel密码】Excel工作表不能复制或移动

为什么excel文件打开之后&#xff0c;工作表里是可以编辑的&#xff0c;但是想要移动工作表或者复制、重命名等操作&#xff0c;这是什么原因&#xff1f;其实这是因为设置了工作簿保护&#xff0c;设置了保护的工作簿无法对整张工作表进行操作。 想要取消这种保护&#xff0c;…