正则表达式超详细讲解

news/2025/2/5 6:28:59/

欢迎并且感谢大家指出我的问题,由于本人水平有限,有些内容写的不是很全面,只是把比较实用的东西给写下来,还有对一些常用的正则表达式进行收集整理,如果有写的不对的地方,还希望大家多多指教!谢谢大家!🥰

        在我第一次接触到正则表达式的时候我就很纳闷,到底谁是谁研究出这么多符号的组合,就那么一个字符规则校验就足以使那么多程序员为之抓狂。我查阅了很多资料和参考文献,将正则表达式的很多知识总结到了一起,废话不多说直接开始。

什么是正则表达式

        正则表达式是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。通俗的讲就是校验字符串是否满足规则或者在文本查找满足要求的内容。我在这里给大家举个简单的例子。

        如果我需要对一组qq号(字符串)进行检验,例如,要求qq号必须是6位到20位之内的,不能以0开头,还必须全是数字。按照正常来说,我需要写一个比较复杂的检测方法。像下面这个是不是看起来比较麻烦。

java">public static boolean checkQQ(String qq) {//规则:6位及20位之内,0不能在开头,必须全部是数字int len = qq.length();if (len < 6 || len > 20) {return false;}//0不能在开头if (qq.startsWith("0")) {return false;}//必须全部是数字for (int i = 0; i < qq.length(); i++) {char c = qq.charAt(i);if (c < '0' || c > '9') {return false;}}return true;
}

        但是如果我们要是使用正则表达式的话只需要一行代码即可,看起来是不是超级哇塞,超级简洁。

java">qq.matches("[1 - 9]\\d{5,19}");

        在Java中可以使用matches方法:String类的matches方法用于尝试将整个字符串与给定的正则表达式进行匹配,如果整个字符串匹配该正则表达式则返回true,否则返回false。 

元字符

元字符:即为有特定含义的字符,常见的元字符如下

常用的元字符(只能匹配一个字符)
代码说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始(在集合字符里[^a]表示非(不匹配)的意思
$匹配字符串的结束
1. 点号(.

        点号是一个非常常用的元字符,它可以匹配除换行符之外的任意单个字符。例如,正则表达式 a.c 可以匹配 "abc"、"a1c"、"a@c" 等字符串。这是因为点号在这里代表了任意一个非换行的字符,只要满足 "a" 开头,"c" 结尾,中间是任意单个字符的模式,都能被匹配。需要注意的是,不同的编程语言或工具可能对换行符的定义有所不同,有些可能会将回车符(\r)、换行符(\n)或它们的组合都视为换行情况。

2. 星号(*

        星号用于表示匹配前面的元素零次或多次。例如,正则表达式 ab*c 可以匹配多种情况。当 b 出现零次时,它可以匹配 "ac";当 b 出现一次时,能匹配 "abc";当 b 出现多次时,像 "abbbc" 也能被成功匹配。这是因为星号允许前面的 b 字符出现任意次数,包括零次。

3. 加号(+

        加号与星号类似,但它要求前面的元素至少出现一次。以正则表达式 ab+c 为例,它可以匹配 "abc"、"abbbc" 等字符串,但不能匹配 "ac",因为 b 至少要出现一次才能满足该正则表达式的模式。

4. 问号(?

        问号表示匹配前面的元素零次或一次。例如,正则表达式 ab?c 可以匹配 "ac"(此时 b 出现零次)和 "abc"(b 出现一次)。问号常用于表示某个字符或一组字符是可选的情况。

5. 花括号({n}{n,}{n,m}

        花括号用于精确控制前面元素的匹配次数,有三种常见的用法:

  • {n}:精确匹配前面的元素 n 次。例如,a{3} 只能匹配 "aaa",如果文本中是 "aa" 或 "aaaa" 则无法匹配。
  • {n,}:匹配前面的元素至少 n 次。例如,a{2,} 可以匹配 "aa"、"aaa"、"aaaa" 等,只要 a 的连续出现次数不少于 2 次即可。
  • {n,m}:匹配前面的元素 n 到 m 次。例如,a{2,4} 可以匹配 "aa"、"aaa"、"aaaa",但不能匹配 "a" 或 "aaaaa"。
6. 方括号([ ]

方括号用于定义一个字符集合,匹配方括号内的任意一个字符。例如,[abc] 可以匹配 "a"、"b" 或 "c"。方括号内还可以使用连字符表示字符范围,如 [a-z] 可以匹配任意小写字母,[0-9] 可以匹配任意数字。此外,方括号内的字符顺序不影响匹配结果,[abc] 和 [cba] 的匹配效果是一样的。

7. 脱字符(^)

脱字符在正则表达式中有两种常见用法:

  • 在方括号内使用时,表示取反,即匹配不在方括号内的任意字符。例如,[^abc] 可以匹配除 "a"、"b"、"c" 之外的任意字符,像 "d"、"1"、"@" 等都能被匹配。
  • 正则表达式开头使用时,表示匹配字符串的开头。例如,^abc 表示只有以 "abc" 开头的字符串才能被匹配,对于 "xyzabc" 这样的字符串则无法匹配。
8. 美元符号($

美元符号用于表示匹配字符串的结尾。例如,abc$ 表示只有以 "abc" 结尾的字符串才能被匹配,像 "testabc" 可以匹配,但 "abcdef" 则无法匹配。

  • ^:表示匹配字符串的开头,确保邮箱地址从这里开始,避免匹配到包含邮箱地址但不是以其开头的字符串。
  • [a-zA-Z0-9._%+-]+:匹配邮箱用户名部分。方括号内定义了允许的字符集合,包括字母(大小写均可)、数字、点号、下划线、百分号、加号和减号。+ 表示这些字符至少出现一次,因为邮箱用户名不能为空。
  • @:匹配邮箱地址中的 "@" 符号,这是邮箱地址的关键分隔符。
  • [a-zA-Z0-9.-]+:匹配域名部分,允许包含字母、数字、点号和减号。同样,+ 表示这些字符至少出现一次。
  • \.:匹配域名中的点号,由于点号是元字符,需要使用反斜杠进行转义。
  • [a-zA-Z]{2,}:匹配顶级域名,由至少两个字母组成。常见的顶级域名如 ".com"、".cn"、".org" 等都满足这个规则。
  • $:表示匹配字符串的结尾,确保邮箱地址到这里结束,避免匹配到包含邮箱地址但后面还有其他多余字符的情况。

转义字符

        当我们需要匹配元字符本身时,就需要使用反斜杠(\)进行转义。因为元字符在正则表达式中有特殊含义,直接使用会被解释为相应的模式匹配规则。例如,要匹配点号(.),就需要使用 \.;要匹配反斜杠本身,需要使用 \\。在不同的编程语言中,由于字符串本身也可能使用反斜杠进行转义,所以有时需要使用双反斜杠来表示一个真正的反斜杠。例如,在 Python 中,要匹配一个点号,正则表达式字符串需要写成 r'\.'(使用原始字符串避免 Python 字符串本身的转义)。

常用的反义字符(只能匹配一个字符)
代码/语法说明
\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结束的位置
[^x]匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这几个字母以外的任意字符

字符类

字符类(只匹配一个字符)
代码说明
[abc]只能是 a, b, 或 c
[^abc]除了 a, b, c 之外的任何字符
[a-zA-Z]a 到 z A 到 Z,包括(范围)       
[a-d[m-p]]a 到 d,或 m 到 p
[a-z&&[def]]a-z 和 def 的交集。为:d, e, f
[a-z&&[^bc]]a-z 和非 bc 的交集。(等同于 [ad-z])
[a-z&&[^m-p]]a 到 z 和除了 m 到 p 的交集。(等同于 [a-lq-z])

限定字符

常用的限定字符如下

常用的限定符
代码/语法说明
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次

字符分枝

字符分枝多用于满足不同情况的选择,用“|”将不同的条件分割开来,比如有些固定电话区号有三位,有些有四位,这个时候可以采用字符分枝

例如:\d{3}-\d{8}|\d{4}-\d{8}  可以匹配两种不同长度区号的固定电话

下边的IP地址正则表达式也有用到字符分枝

字符分组

字符分组多用于将多个字符重复,主要通过使用小括号()来进行分组

形如:(\d\w){3} 重复匹配3次(\d\w)

常用于表示IP地址   形如: ^(?:(?: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]?)$

解析:先把IP地址分为两部分一部分是123.123.123. 另一部分是123,又因Ip最大值为255,所以先使用分组,然后在组里边再进行选择,组里也有三部分,0-199,200-249,250-255,分别和上述的表达是对应,最后还要注意分组之后还要加上一个.,因为是元字符所以要转义故加上\. 然后再把这部分整体看做是一个组,重复三次,再加上仅有数字的一组也就是不带\.的那一组即可完成IP地址的校验


懒惰匹配和贪婪匹配

贪婪匹配:正则表达式中包含重复的限定符时,通常的行为是匹配尽可能多的字符。

懒惰匹配,有时候需要匹配尽可能少的字符。

        在正则表达式中,默认的匹配模式是贪婪匹配,即尽可能多地匹配字符。例如,正则表达式 a.*b 对于字符串 "aabab" 会匹配整个字符串 "aabab",因为 .* 会尽可能多地匹配字符,直到遇到最后一个 "b"。

        而非贪婪匹配则是尽可能少地匹配字符,通过在量词后面加上问号 ? 来实现。例如,正则表达式 a.*?b 对于字符串 "aabab" 会匹配 "aab",因为 .*? 会尽可能少地匹配字符,一旦遇到第一个 "b" 就停止匹配。

八、后向引用

后向引用用于重复搜索前面某个分组匹配的文本。

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推

示例:\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。

这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1)。

你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b

零宽断言

        有时候需要查找某些匹配之前或之后的东西,这个时候就需要用到们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言

        零宽断言是一种特殊的正则表达式语法,它用于在不消耗字符的情况下进行位置匹配。也就是说,零宽断言只检查某个位置是否满足特定的条件,而不会将匹配到的字符作为结果的一部分。常见的零宽断言有以下几种:

1. 正向先行断言((? = ...)

        正向先行断言用于检查某个位置后面的字符是否满足特定的模式。例如,正则表达式 \w+(?=\d) 可以匹配后面紧跟着一个数字的单词字符序列。对于字符串 "abc123",它会匹配 "abc",因为 "abc" 后面紧跟着数字 "1"。

2. 负向先行断言((?!...)

        负向先行断言用于检查某个位置后面的字符是否不满足特定的模式。例如,正则表达式 \w+(?!\d) 可以匹配后面不紧跟着数字的单词字符序列。对于字符串 "abc def123",它会匹配 "abc" 和 "def",因为 "abc" 后面不是数字,而 "def" 虽然后面跟着数字,但在匹配 "def" 时检查到后面不是数字的条件是满足的。

3. 正向后行断言((?<=...)

        正向后行断言用于检查某个位置前面的字符是否满足特定的模式。例如,正则表达式 (?<=\$)\d+ 可以匹配前面紧跟着美元符号的数字序列。对于字符串 "$123",它会匹配 "123"。

4. 负向后行断言((?<!...)

        负向后行断言用于检查某个位置前面的字符是否不满足特定的模式。例如,正则表达式 (?<!\$)\d+ 可以匹配前面不紧跟着美元符号的数字序列。对于字符串 "123 $456",它会匹配 "123"。

实践

Java 中通过 java.util.regex 包来支持正则表达式的使用。以下是一些示例:

java">import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexExample {public static void main(String[] args) {// 匹配手机号码String pattern = "^1[3-9]\\d{9}$";String phone = "13800138000";Pattern r = Pattern.compile(pattern);Matcher m = r.matcher(phone);if (m.matches()) {System.out.println("手机号码格式正确");} else {System.out.println("手机号码格式错误");}// 查找字符串中的单词String text = "Hello, World!";Pattern wordPattern = Pattern.compile("\\w+");Matcher wordMatcher = wordPattern.matcher(text);while (wordMatcher.find()) {System.out.println(wordMatcher.group());}}
}

 


http://www.ppmy.cn/news/1569433.html

相关文章

50【Windows与Linux】

大家可能有些人听过Linux系统&#xff0c;很多初学者被灌输的理念就是服务器必须要装Linux系统 什么是系统&#xff1f; 比如你的电脑是Windows系统的&#xff0c;你手机是Android系统的&#xff0c;物理设备都需要系统&#xff0c;系统你可以理解成直接控制物理设备的一个东…

Mac上的虚拟化软件推荐

在Mac上运行虚拟化软件是一个非常实用的选择,可以满足不同用户的需求,包括运行Windows操作系统、Linux系统或开发环境等。以下是几款推荐的虚拟化软件及其特点: 1. Parallels Desktop 适用平台:Intel和Apple M系列Mac电脑。功能:支持Windows、Linux和macOS等多种操作系统…

向上调整算法(详解)c++

算法流程&#xff1a; 与⽗结点的权值作⽐较&#xff0c;如果⽐它⼤&#xff0c;就与⽗亲交换&#xff1b; 交换完之后&#xff0c;重复 1 操作&#xff0c;直到⽐⽗亲⼩&#xff0c;或者换到根节点的位置 这里为什么插入85完后合法&#xff1f; 我们插入一个85&#xff0c;…

IFeatureWorkspace.CreateFeatureClass(),报错对COM组件的调用返回了错误 HRESULT E_FAIL

1、问题描述&#xff1a;在AE开发中&#xff0c;新增一个空的shpfile文件的时候&#xff0c;报错&#xff0c;如下图&#xff1a; 2、原因分析&#xff1a;产生此问题的原因是未设置默认字段的默认参数&#xff0c;特别是未设置IGeometryDef 参数。 3、解决方案&#xff1a;在…

视频拼接,拼接时长版本

目录 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg imageio&#xff0c;适合视频较短 视频较长&#xff0c;分辨率较大&#xff0c;这个效果很好&#xff0c;不耗用内存 ffmpeg import subprocess import glob import os from nats…

RabbitMQ深度探索:死信队列

死信队列产生背景&#xff1a; RabbitMQ 死信队列俗称 备胎队列&#xff1a;消息中间件因为某种原因拒收该消息后&#xff0c;可以转移到私信队列中存放&#xff0c;死信队列也可以有交换机和路由 key 等 生产死信队列的原因&#xff1a; 消息投递到 MQ 存放&#xff0c;消息已…

一文速览DeepSeek-R1的本地部署——可联网、可实现本地知识库问答:包括671B满血版和各个蒸馏版的部署

前言 自从deepseek R1发布之后「详见《一文速览DeepSeek R1&#xff1a;如何通过纯RL训练大模型的推理能力以比肩甚至超越OpenAI o1(含Kimi K1.5的解读)》」&#xff0c;deepseek便爆火 爆火以后便应了“人红是非多”那句话&#xff0c;不但遭受各种大规模攻击&#xff0c;即便…

Python爬虫:1药城店铺爬虫(完整代码)

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…