正则表达式笔记(一)

本文详细讲解了正则表达式中的元字符如^、$、、.|[]等,以及文字匹配中的字符类、限定符、替换和分组的用法,还包括懒惰限定符和零宽断言。深入理解这些概念有助于高效处理字符串匹配问题,如HTML标签解析和内容提取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、元字符

在正则表达式中,元字符(Metacharacter)是一类非常特殊的字符,它能够匹配一个位置或字符集合中的一个字符,如、\w等。根据功能,元字符可分为两种类型:匹配位置的元字符和匹配字符的元字符。

1.1 元字符表

如果大家别正则表单式中的字符的作用区分开,可能更好去理解。

模式描述
^匹配字符字符串的开头
$匹配字符串的末尾
\b匹配一个单词边界,也就是单词和空格间的位置。例如:’er\b’可以匹配"never"中的er ,但不能匹配"verb" 中的er
.匹配除“\n”之外的任何字符。要匹配包括“\n"在内的任何字符,要使用 '[.\n]'的模式
\w匹配包括下划线的任意单词字符(汉字在内),等价于 ‘[A-Za-z0-9_]’
\W匹配任意非单词字符 ,等价于 ‘[^A-Za-z0-9_]’
\s匹配任何空白字符,包括空格,制表符,换页符。等价于[\f\n\r\t\v]
\S匹配任意非空字符,等价于[^\f\n\r\t\v]
\d匹配一个数字字符,等价于[0-9]
\D匹配一个非数字字符,等价于 [^0-9]

1.2 匹配位置的元字符

匹配位置的元字符包括3个字符:^、$和\b。其中,^(脱字符号,通常在文章中插入字时使用)和$(美元符号)只匹配一个位置,它们分别匹配行的开始和结尾。

1.2.1 ^

放在字符的前边。
如下面例子,会匹配以“string"开始的行,且匹配出来的结果只有”string“。

^string

在这里插入图片描述

1.2.2 $

放在字符的后边,和^一样,也只会匹配到该字符。

如果是

^string$
^$  //空行

则,匹配的行,只有字符串string

1.2.3 \b

元字符\b和^、s具有相似性,它也是匹配一个位置。b可以匹配单词的开始和结尾,即单词的分界处。
通常情况下,英文单词之间往往由空格符号、标点符号或换行符号来分隔,但是元字符\b不匹配空格符号、标点符号和换行符号中的任何一个,它仅仅匹配一个位置。
以下正则表达式匹配以“Str”开头的字符串,如“String”、“String Format”等。q且只匹配除“Str"

\bStr

什么理解所说的单词分界处呢?下面我们来看看这个例子:
在这里插入图片描述
可以看到,在单词里边的in是没有被匹配到的,而且有一点,它是以单词为分界的。如果下面的例子换成^in就什么也匹配不上了。

  • .\bmy\b,则会匹配到一个完整的my单词,如果my出现在一个单词的开头是匹配不上的。

1.3 匹配字符的元字符

如果单独使用只会匹配到一个字符,在上面也提到了

二、文字匹配

2.1、字符类

在正则表达式中,元字符如果没有量词的情况下通常一次只能匹配一个位置或字符集合中的一个字符
通常情况下,如果要匹配数字、字母、空白等字符时,可以直接使用与这些集合相对应的元字符。
然而,如果要匹配的字符集合(如集合[0,1 1,2,3,4,5]) 没有与之相对应的元字符时,则需要自定义匹配的字符集合。
此时,可以使用字符类解决这个问题。字符类是一个字符集合,如果该字符集合中的任何一个字符被匹配,则它就会找到该匹配项。

字符类是正则表达式中的“迷你”语言,可以在方括号“[ ]”中定义。最简单的字符类由方括号“[ ]”和一个字母表构成,如元音字符类 [aeiou]。
以下正则表达式匹配数字0、1、2、3、4、5、6中的任何一个。

[012345]
//也可以是 [543210]
//意思就是顺序是看起来好看罢了

如果方括号中字母或数字太多就不方便了,那么就可以使用==连接符-==来定义范围。(范围是由ASCII表中的顺序定义的)

[0-9]
//d等价于[0123456789]

特殊情况

[-9]

只能匹配到9或者-。所以使用连接符必须有始有终。

  • 注意: 在字符集中使用元字符时,不会进行转义运算。就是说元字符的作用消失了。如
[.]

只能匹配到.

2.2、限定符

正则表达式的元字符一次一般只能匹配一个位置或一个字符,如果想要匹配零个、一个或多个字符时,则需要使用限定符。限定符用于指定允许特定字符或字符集自身重复出现的次数。如{n}表示重复n次、{n}表示重复至少n次、{n,m}表示重复至少n次,最多m次。

常用限定符的说明如表1.5所示。

字符说明
{n}n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。
{n,}n 是一个非负整数。至少匹配n 次。例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等价于 ‘o+’。‘o{0,}’ 则等价于 ‘o*’。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,“o{1,3}” 将匹配 “fooooood” 中的前三个 o。‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。
*匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。
+匹配前面的子表达式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 中的"do" 。? 等价于 {0,1}。
*?尽可能少地使用重复的第一个匹配
+?尽可能少地使用重复但至少使用一次
??使用零次重复(如有可能)或一次重复
{n}?等同于{n}
{n,}?尽可能少地重复使用n次
{n,m}?介于n次和m次之间,尽可能少地重复使用

2.2.1 *、+、?的区别

通过一个例子展示

在这里插入图片描述
+
在这里插入图片描述
*
在这里插入图片描述
通过对比我们可以知道*+和?的结合体。

2.2.2懒惰限定符

字符说明
*?尽可能少地使用重复的第一个匹配
+?尽可能少地使用重复但至少使用一次
??使用零次重复(如有可能)或一次重复
{n}?等同于{n}
{n,}?尽可能少地重复使用n次
{n,m}?介于n次和m次之间,尽可能少地重复使用

这些字符匹配遵循懒惰匹配。如果把去掉就是贪婪匹配

  • 懒惰匹配,即匹配尽可能少的字符,但是要匹配出所有的结果。
  • 检索结果中,每遇到一次关键字,都会停下来,重新检索。如下面这个例子:

在这里插入图片描述
如果是a.*d
结果就是abcdakdjd
这就是贪婪匹配,顾名思义,很贪婪,要最大限度的占用字符串。

以上两种,一个是尽量匹配最短串,一个是要匹配最长串。

2.3、字符的运算


1.3.1 替换 "|"

最简单的替换是使用字符|表示,它表示如果某一个字符串匹配了正则表达式中的字符|的左边或右边的规则,那么该字符也匹配了该正则表达式。

0\d{2}-\d{7}|0\d{3}[-]?\d{7}

其中[-]? 表示-可有可无

  • 注意:在匹配的时候首先匹配字符的左侧部分,如果匹配成功就不匹配了。

2.3.2 分组 "("和")"

分组又称为子表达式,即把一个正则表达式的全部或部分分成一个或多个组
其中,分组使用的字符为“(”和“)”,即左圆括号和右圆括号。

分组之后,可将在==“(”和“)”之间==的表达式看成一个整体来处理。以下正则表达式可以匹配重复出现字符串“abc”一次或两次的字符串。
此时,表达式将“abc”看成一个整体来进行重复匹配。

(abc){1.2}

如以下正则表达式可以匹配简单的IP地址:

(\d{1,3}){3}\d{1,3}

2.3.3 反向引用

当一个正则表达式被分组之后,每一个组将自动被赋予一个组号,该组号可以代表该组的表达式。
其中,组号的编制规则为:从左到右、以分组的左括号“(”为标志,第一个分组的组号为1,第二个分组的组号为2,依此类推。
反向引用提供了查找重复字符组的简便方法。它们可以被认为是再次匹配同一个字符串的快捷指令。
反向引用可以使用数字命名(即默认名称)的组号,也可以使用指定命名的组号。具体说明如表所示。

表达式说明
\数字使用数字命名的反向引用
\k<name>使用指定命名的反向引用

如:

\b(\w)\1\b

只匹配含有两个重复字符且长度为2的单词

采用自定义分组名的方式
如上边的将\w命名为"Word的方法有两种

(?<word>\w)
(?'word'\w)

上面的式子就可以等价于

\b(?<word>\w)\k<word>\b

2.4 零宽断言

零宽断言的意思是(匹配宽度为零,满足一定的条件/断言) 我也不知道这个词语是那个王八蛋发明的,简直是太拗口了。

零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。

断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配。

其中零宽断言又分四种

先行断言 也叫零宽度正预测先行断言(?=表达式) 表示匹配表达式前面的位置

例如 [a-z]*(?=ing) 可以匹配cooking singing 中的cook与sing

注意:先行断言的执行步骤是这样的先从要匹配的字符串中的最右端找到第一个ing(也就是先行断言中的表达式)然后 再匹配其前面的表达式,若无法匹配则继续查找第二个ing 再匹配第二个 ing前面的字符串,若能匹配 则匹配

例如:.*(?=ing) 可以匹配cooking singing 中的cooking sing 而不是 cook

后发断言 也叫零宽度正回顾后发断言 (?<=表达式) 表示匹配表达式后面的位置

例如(?<=abc).* 可以匹配abcdefg中的defg

注意:后发断言跟先行断言恰恰相反 它的执行步骤是这样的:先从要匹配的字符串中的最左端找到第一个abc(也就是先行断言中的表达式)然后 再匹配其后面的表达式,若无法匹配则继续查找第二个abc 再匹配第二个abc后面的字符串,若能匹配 则匹配

例如(?<=abc).* 可以匹配abcdefgabc中的defgabc 而不是abcdefg

负向零宽断言

负向零宽断言 (?!表达式) 也是匹配一个零宽度的位置,不过这个位置的“断言”取表达式的反值,例如 (?!表达式) 表示 表达式 前面的位置,如果 表达式 不成立 ,匹配这个位置;如果 表达式 成立,则不匹配:同样,负向零宽断言也有“先行”和“后发”两种,负向零宽后发断言为 (?<!表达式)

负向零宽后发断言(?<!表达式)

负向零宽先行断言 (?!表达式)

负向零宽断言要注意的跟正向的一样

匹配HTML

匹配HTML标记

HTML一般由尖括号包围,如<a>、<input>,可以用一下模式进行匹配。

<[a-zA-Z][^>]*>

该正则表达式解释如下。

  • <匹配HTML标记的左尖括号。
  • 字符类[a-zA−Z] , 可以匹配一个英文字母,它匹配HTML标记中除去左尖括号的第一个字符。
  • 字符类[^>]可以匹配除右尖括号之外的任何字符。
  • [^>]*可以匹配空字符串,或者由除右尖括号之外的任何字符组成的字符串。
  • 匹配HTML标记的右尖括号。

匹配HTML标记之间的内容

(?<=<(?<tag>\w+)>).*(?=<\/\k<tag>>)

<a> dnskj<b>ssk</b></a>为例

  • (?<tag>\w+):这是一个分组匹配的是 a
  • <(?<tag>\w+)>:匹配<a>
  • (?<=<(?<tag>\w+)>):其中?<=是零宽度正回顾后发言。匹配其之后的字符。相当于把<a>去掉
  • .*:匹配dnskj<b>ssk</b>
  • \k<tag>:反引用,相当于a
  • <\/\k<tag>> :匹配</a>
  • (?=<\/\k<tag>>):?=是零宽度正预测先行发言,匹配其之前的字符,相当于把</a>去掉。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落春只在无意间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值