正则表达式

前言

在记录正则表达式的相关内容之前,贴一个正则表达式的在线验证工具,可以直接在这网站上练习正则表达式

RegExr: 学习、构建 和 测试 正则表达式 Test RegEx

常见语法

普通字符匹配

直接使用想要的字符进行匹配,比如如果你只想在"你好世界"这个字符串中提取"你好"两个字符时,直接使用这两个字符作为匹配模式即可

. :匹配任意一个字符

不同于输入自己想要的字符,. 可以代表任意一个字符, 如下图所示,, 可以代表"你好世界"四个字的任意一个字

*:对字符进行任意次数的匹配

*代表可以对字符进行任意次数的匹配,如下图所示,我想要得到文本中的后半段句子,包括,那么我就可以使用表达式 ,.*

其中,表示匹配字符, .表示匹配,后边的任意一个字符,*表示匹配任意一个字符任意次

+:对字符进行一次或者多次匹配

不同于*,+表示对字符匹配至少一次,不能包含0次,而*可以匹配0次,也就是字符可以不出现

在该例子中,我们将上述的正则模式更换为**,.+**

可以看到我们只匹配到了,后边有字符的部分,而对于没有字符的部分无法获取到,因为+不能匹配0次

?:对字符进行匹配0次或者一次

?表示对字符匹配0次或者1次,同样见下例

{}:自定义字符匹配次数

自定义指定对字符的匹配次数,见下例,只对,后的字符出现两次的进行提取

当然也可以多写几个任意次数

[]:模糊匹配

含义:表示要匹配的几个指定字符之一。

[abc]可以匹配a、b、c中任意一个字符,等价于:[a-c]

如下,匹配字符串中的字符"的","式","呀"中的任意一个,如果匹配到就返回,匹配不到不返回

中括号表达式的其他用法还有一个其他用法,该用法与模糊匹配的含义完全不同,不要混淆

即,如果在中括号中使用^则表示非,不匹配在中括号中的字符集合。

python 复制代码
import re

content = 'a1b2c3d4e5'
for temp in re.findall(r'[^\d]', content):
    print(temp,end=" ")

上述表达式中表示匹配字符串中,不是数字的所有字符,结果如下

():分组匹配

分组匹配常用于在字符串中提取我们想要的部分内容,如下所示,如果我们只想得到字符串中的水果名字,而不想得到其后的中文, 使用分组即可得到结果

该正则表达式表示,提取出以中文,结尾的()中的若干字符

再如以下示例,我想得到字符串中的人物姓名及其对应的手机号码,我们也可以使用如下正则表达式进行提取,其含义为:

  • (.+),: 匹配任意字符(除换行符外)一次或多次,并将匹配的结果保存到一个分组中,然后匹配一个逗号。
  • .+: 匹配任意字符(除换行符外)一次或多次。
  • (.{11}): 匹配任意字符(除换行符外)恰好11次,并将匹配的结果保存到一个分组中。

贪婪模式与非贪婪模式

假如现在我们有一个重复的标签内容:

html 复制代码
aa<div>test1</div>bb<div>test2</div>cc

假如我们现在想得到div标签,该如何得到呢?

贪婪模式

如果使用以下语句

python 复制代码
source = 'aa<div>test1</div>bb<div>test2</div>cc'

for temp in re.findall(r'<div>.*</div>', source):
    print(temp)

最终得到的结果是:

html 复制代码
<div>test1</div>bb<div>test2</div>

非贪婪模式

而如果使用以下语句:

python 复制代码
import re

source = 'aa<div>test1</div>bb<div>test2</div>cc'

for temp in re.findall(r'<div>.*?</div>', source):
    print(temp)

最终得到的结果是

html 复制代码
<div>test1</div>
<div>test2</div>

很显然,第二种结果才是我们想要的

可以这样认为,贪婪模式,就是在整个表达式匹配成功的前提下,尽可能多的匹配,也就是所谓的"贪婪",通俗点讲,就是看到想要的,有多少就捡多少,除非再也没有想要的了。

非贪婪模式,就是在匹配到第一个"</div>"时使整个表达式匹配成功时就结束匹配,不再向右尝试,也就是在整个表达式匹配成功的前提下,尽可能少的匹配,匹配结果为"<div>test1</div>"。

字符转义

反斜杠\在正则表达式中有多重用途,例如在以下文本中搜索所有.之前的字符串,也包含.本身。

复制代码
苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的

如果我们将正则表达式写成:.*.,肯定是不正确的,因为.是一个元字符,具有特殊含义。直接出现在正则表达式中不能表示.这个字符本身。

解决方式:使用\转义。

python 复制代码
import re

content = '''
苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的
'''

for temp in re.findall(r'.*\.', content):
    print(temp)

某种字符类型的匹配

在反斜杠后链接一些字符可以表示某种类型的一个字符,如下:

|-----|-------------------------------------|-----------------------|
| | 含义 | 等价表达式 |
| \d | 匹配0-9之间任意一个数字字符 | [0-9] |
| \D | 匹配任意一个不是0-9之间的数字字符 | [^0-9] |
| \s | 匹配任意一个空白字符 ,包括空格、tab、换行符等 | [\t\n\r\f\v] |
| \S | 匹配任意一个非空白字符 | [^\t\n\r\f\v] |
| \w | 匹配任意一个文字字符,包括大小写字母、数字、下划线 | [a-zA-Z0-9_] |
| \W | 匹配任意一个非文字字符 | [^a-zA-Z0-9_] |

首尾匹配与单行、多行模式

^表示匹配文本的开头 位置。在正则表达式中可以设置单行模式多行模式

  • 单行模式:表示匹配整个文本的开头位置

  • 多行模式:表示匹配文本每行的开头位置

在下面的文本中,每行最前面的数字表示水果的编号,最后的数字表示价格。

001-苹果价格-60

002-橙子价格-70

003-香蕉价格-80

如果我们要提取所有的水果编号 ,用这样的正则表达式:^\d+

python 复制代码
import  re

content = '''001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80
'''

res=re.findall(r'^\d+',content,re.M)
print(res)

结果如下:

上述表达式的含义是:取出以任意数字开头的若干个数字字符

参数re.M表示匹配多行,如果没有这个参数,则只能匹配到001

同样的道理,如果我们想得到水果的价格 ,则可以使用这样的表达式:\d+$

cpp 复制代码
import  re

content = '''001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80
'''

res=re.findall(r'\d+$',content,re.M)
print(res)

结果如下:

DOTALL参数

DOTALL标记允许点号匹配所有字符,包括换行符。这对于需要处理包含换行符的文本时非常有用,因为默认情况下点号无法匹配换行符。

在以下html代码中提取所有的职位名称:

html 复制代码
<div class="el">
        <p class="t1">           
            <span>
                <a>Python开发工程师</a>
            </span>
        </p>
        <span class="t2">南京</span>
        <span class="t3">1.5-2万/月</span>
</div>
<div class="el">
        <p class="t1">
            <span>
                <a>java开发工程师</a>
            </span>
		</p>
        <span class="t2">苏州</span>
        <span class="t3">1.5-2/月</span>
</div>

如果直接使用表达式class=\"t1\">.*?<a>(.*?)</a>会发现匹配不上,因为t1<a>之间有两个空行,这时就需要.匹配所有字符了。

python 复制代码
import re

content = '''
<div class="el">
        <p class="t1">           
            <span>
                <a>Python开发工程师</a>
            </span>
        </p>
        <span class="t2">南京</span>
        <span class="t3">1.5-2万/月</span>
</div>
<div class="el">
        <p class="t1">
            <span>
                <a>java开发工程师</a>
            </span>
		</p>
        <span class="t2">苏州</span>
        <span class="t3">1.5-2/月</span>
</div>
'''


for temp in re.findall(r'class=\"t1\">.*?<a>(.*?)</a>', content, re.DOTALL):
    print(temp)
相关推荐
平头哥在等你1 小时前
python特殊字符序列
开发语言·python·正则表达式
zwjapple1 天前
typescript里面正则的使用
开发语言·javascript·正则表达式
licy__2 天前
正则表达式语法详解(python)
数据库·mysql·正则表达式
风动也无爱2 天前
Java的正则表达式和爬虫
java·爬虫·正则表达式
运维小文3 天前
linux中的特殊符号
linux·正则表达式·shell·linux命令
南暮思鸢3 天前
强大的正则表达式——Hard
web安全·网络安全·正则表达式·交互式·write up·ctf比赛·hackergame 2024
赶紧回家去3 天前
正则表达式常用字符
正则表达式
白萝卜弟弟3 天前
【JAVA】正则表达式中的正向肯定预查
java·正则表达式
高锰酸钾_3 天前
Java 正则表达式详解及实用案例
java·正则表达式
追梦不止~3 天前
正则表达式
正则表达式