正则表达式

前言

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

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

常见语法

普通字符匹配

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

. :匹配任意一个字符

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

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

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

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

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

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

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

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

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

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

 

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

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

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

[]:模糊匹配

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

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

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

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

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

import re

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

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

():分组匹配

分组匹配常用于在字符串中提取我们想要的部分内容,如下所示,如果我们只想得到字符串中的水果名字,而不想得到其后的中文,  使用分组即可得到结果
该正则表达式表示,提取出以中文,结尾的()中的若干字符

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

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

贪婪模式与非贪婪模式

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

aa<div>test1</div>bb<div>test2</div>cc

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

贪婪模式

如果使用以下语句

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

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

最终得到的结果是:
 

<div>test1</div>bb<div>test2</div>

非贪婪模式

而如果使用以下语句:

import re

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

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

最终得到的结果是

<div>test1</div>
<div>test2</div>

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

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

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

字符转义

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

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

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

解决方式:使用\转义。

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+

import  re

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

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

结果如下: 

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

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

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

import  re

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

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

结果如下:

DOTALL参数

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

在以下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>之间有两个空行,这时就需要.匹配所有字符了。

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值