正则表达式基础

本文深入介绍了正则表达式的基础知识,包括匹配文本、特殊字符、字符类别、重复匹配和位置匹配等概念,还提供了多个实例来演示如何在实践中应用正则表达式。通过对《正则表达式必知必会》一书的提炼,帮助读者理解和掌握正则表达式的核心功能。

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

本文内容是对书籍《正则表达式必知必会》的提炼

 

正则表达式

用来匹配和处理文本的字符串,主要功能是查找和替换。

正则的语法简单,难点在于使用这些语法,学习方法是多实践。

纯文本

Ben

匹配Ben这个文本,注意区分大小写,Ben和ben是不一样的

英文句号,匹配任意一个字符

salsa.

可以匹配,salsa1或者salsa2

.a.

可以匹配,aaa或者1ab

有一个英文句号不能匹配,那就是换行符

反斜杠,匹配特殊字符

如果表达式中需要的就是一个英文句号,就在句号前面加一个反斜杠

.a.\.

可以匹配,aaa. 或者 1ab.

要匹配反斜杠,就在前面在加个反斜杠

匹配多个字符中的一个

[ns]a\.xls

可以匹配,na.xls或者sa.xls,但是不会匹配 aa.xls

 

[0-9] = [0123456789]

[a-z] = [abcd….xyz]

[A-Z0-9a-z] = [ABC…XYZ012…789abc…xyz]

取非匹配

除了这些字符,其他的都可以匹配

[ns]a[^0-9]\.xls

可以匹配 naa.xls,不能匹配 na0.xls

空白元字符

元字符

说明

[\b]

回退一个字符

\f

换页符

\n

换行符

\r

回车符

\t

制表符

\v

垂直制表符

 

在windows里面\r\n匹配一个换行,但是unix系统中\n就可以匹配换行

匹配特定的字符类别

匹配数字

元字符

说明

\d

任何一个数字字符,等价于[0-9]

\D

任何一个非数字字符,等价于[^0-9]

匹配字母和数字

元字符

说明

\w

任何一个字母(大小写均可)数字字符或下划线,等价于[a-zA-Z0-9_]

\W

任何一个非字母数字字符和下划线,等价于[^a-zA-Z0-9_]

匹配空白字符

元字符

说明

\s

任何一个空白字符,等价于[\f\n\t\r\v]

\S

任何一个非空白字符,等价于[^\f\n\t\r\v]

使用POSIX字符类

许多正则表达式都支持POSIX字符类

重复匹配

正则表达式的真正威力所在就是重复匹配

+号,匹配一个或者多个字符

问题,如何写一个邮箱匹配模式

\w@\w\.\w

可是这个只能匹配 a@b.c 这种,不能匹配 b@forta.comhow@forta.com

使用+号就可以实现这个功能

\w+@\w+\.\w+

但是我们发现,这个模式无法匹配 ben.forta@forta.comben@forta.help.com

我们可以使用+号来匹配字符集

[\w.]+@[\w.]+\.\w+

最后一个+号没有匹配字符集的原因是那样会匹配 ben.forta@forta.com. 这种最后有英文句号的情况

但是我们这个模式可以匹配邮箱最前面有英文句号的情况 .ben.forta@forta.com

注意:在字符集合里面,特殊字符可以不用转义,但是也可以转义,[\w.] == [\w\.]

*号,匹配0个或多个字符

*号和+号类似,只是+号至少匹配一个,而*号匹配可有可无的字符或字符集

利用*号,我们可以解决上面的问题,先用\w+匹配第一个字符,然后用[\w.]*匹配@之前,第一个字符之后的字符

\w+[\w.]*@[\w.]+\.\w+

疑问:去掉第一个加号,答案也是对的吧? \w[\w.]*@[\w.]+\.\w+

解答:答案也是对的,但是第一种在语义上更容易理解

?号,匹配0个或一个字符

假设我们要匹配网址URL

http://[\w./]+

可以匹配 http://forta.com 但是不能匹配 https://forta.com

修改成

https?://[\w./]+

即可

{}花括号,匹配的重复次数

?号,*号和+号都不能限制匹配的确定次数,比如我想只匹配6次,这就需要使用花括号

问题:匹配十六进制颜色码,需要匹配#034EFD,#FFFFFF这样的字符串

解法1:

#[0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]

解法2:

#[0-9a-fA-F]{6}

匹配的区间

如果要匹配至少多少次,最多多少次呢,可以使用{2, 4},这样表示至少匹配2次,最多匹配4次

如果只说明至少匹配多少次,没说最多匹配的次数,使用{2, },省略了4,表示至少匹配2次,最多无限次

防止过度匹配

例子:如果我们要匹配网页标签,比如<B>,应该如何匹配

<Bb>.*</Bb>

如果文本是这样的,<B>ak</B> and <B>hk</B>,那么这个模式会将其全部匹配,只得到一条结果,而不是两个结果,因为*,+这些符号默认是贪婪匹配,对于一个结果,它会一直找到文档末尾,所以需要防止过度匹配的时候,要使用这些字符的懒惰版本

贪婪性元字符

懒惰性元字符

*

*?

+

+?

{n, }

{n, }?

懒惰匹配版本模式

<Bb>.*?</Bb>

这样便可以解决问题

位置匹配

\b,单词边界

边界匹配用来解决在什么地方进行字符串匹配操作的问题。

文本:the cat scattered his food all over the room.

模式:

cat

结果:the cat scattered his food all over the room.

\b用来匹配单词的开始和结尾,它匹配的是这样一个位置,这个位置位于一个能够用来构成单词的字符(\w:字母,数字和下划线)和一个不能用来构成单词的字符(\W)之间。

所以使用

\bcat\b

将只匹配第一个cat

如果想要匹配第二个cat呢?使用\B

\Bcat\B

字符串匹配,^(字符串开头) 和 &(字符串结尾)

例子:匹配XML文档

<\?xml.*\?>

可以匹配 <?xml version=”1.0”?>,但是如果这个文本出现在文档的第二行,那这就不是一个xml文档

^<\?xml.*\?>

只要在模式前面加上^,表示匹配字符串开头,就可以解决这个问题

 

例子:匹配web页面的</html>标签,这个标签后面不应该有任何东西

</[Hh][Tt][Mm][Ll]>&

(?m),分行模式

启用分行模式之后,^和&将会匹配每一行的开头和结尾

(?m)必须出现在文档的最前面

(),子表达式

例子1:在网页开发中,经常会使用 &nbsp; 这个来表示空格,比如 Windows&nbsp; &nbsp;2000,显示出来是Windows 2000,

&nbsp;{2, }

0在上面这个例子中,我们试图使用匹配 &nbsp; &nbsp; ,但是因为元字符只是对前一个字符有效,所有我们只能匹配到类似&bnsp;;;;;;;这样的字符串

解决办法,使用子表达式

(&nbsp;){2, }

 

例子2:匹配IP地址

\d{1, 3}\.\d{1, 3}\.\d{1, 3}\.\d{1, 3}

可以匹配,10.0.0.55 这样的IP地址

使用子表达式

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

字表达式的嵌套

例子3:准确IP地址匹配

在例子2中,我们匹配的IP地址模式存在一定的问题,因为IP地址每个数字最大不超过255,可是我们的模式可以匹配999这样的数,在正则表达式中,我们需要定义清除想要什么,不想要什么。

  1. 任何一个1位或2位的数字
  2. 任何一个以1开头的3位数字
  3. 任何一个以2开头,第2位数据在0~4之间的3位数字
  4. 任何一个以25开头,第三位数字在0-5之间的3位数字
(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])))

在这个模式中,| 表示或的意思,在分号的左边和右边最好使用子表达式括起来

回溯引用,前后一致匹配

回溯引用的意思是,模式的后面一部分引用了前面的字表达式。使用\1 ~ \n 来引用前面的子表达式,第一个字表达式就是\1,第二个是\2,依次类推。

例子1:找到网页中所有的标题标签,从h1-h6

模式:

<[Hh][1-6]>.*?</[Hh][1-6]>

这个模式可以匹配到所有的h1-h6,并且是懒惰式搜索,但是有一个问题,就是此模式可以匹配到<h2>..</h3>这样的非法标签,如何解决呢,这就需要使用回溯引用了。

模式:

<([Hh][1-6])>.*?</\1>

将 [Hh][1-6] 变成一个子表达式,然后再后面用 \1 引用,这样\1能匹配的值就和之前的表达式一样,就不会出现匹配到<h2>..</h3>的问题。

 

例子2:有如下一段文本,找到文本中连续重复出现的单词

This is a block of of text.

Several words here are are repeated, and and they should not be.

模式:

[\s]+(\w+)[\s]\1

前后查找

例子1:找到网页文档中<title></title>中包含的内容

模式:

<title>.*?</title>

可以匹配,<title>hello world</title>,但是我们需要的是内容,而不需要<title>这个标签,找到之后还要用代码进行提取,比较麻烦。正则可以实现这个需求,也就是让匹配的文本不出现在结果中。

(?=), 向前查找

后面的匹配结果不出现在结果中。

http://www.baidu.com

ftp://www.forta.com

https://mail.qq.com

例子2:提取URL的协议名

模式:

.*:

匹配结果:http: , ftp: , https: ,虽然结果基本正确,但是我们并不需要用来匹配的冒号:,因为冒号在最后面,所以我们使用向前查找,语法是,?=

模式:

.*(?=:)

结果中就不包含冒号了,需要注意的地方是,?=必须用字表达式括起来。

(?<=)向后查找

和向前查找类似,只是前面的匹配字符不会出现在结果中。

ABC01: $23.45

HGG42: $5.32

BAIDU: $0.23

例子:提取出数据库中的价格。

模式:

\$[0-9.]+

可以匹配到正确的结果,但是我们不需要价格前面的$符号,可以使用向后查找

(?<=\$)[0-9.]+

注意:向前查找所查找的字符串长度是可变的,可以和英文句号,+号之类的元字符结合起来,但是向后查找只能是固定长度的字符串

对前后查找取非(略)

比较少用,不学了

嵌入条件(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值