python正则表达式findall_python 正则表达式findall匹配问题

1.今天在做一道匹配邮箱的题目,发现re.findall()匹配的时候如果有括号,只能取到括号里面的内容:

有以下字符串y,使用正则表达式匹配出字符串中的邮箱地址。

y= '123@qq.comaaa@163.combbb@126.comasdfasfs33333@adfcom'

要是想匹配邮箱地址的话,必须做一些其他的工作,下面提供了三种写法:

import re

y= '123@qq.comaaa@163.combbb@126.comasdfasfs33333@adfcom'

#第一种写法:

ret1=re.findall('[0-9a-z]+@+[0-9a-z]+\.com',y)

print(ret1)

##第二种写法:

ret2=re.findall('(\w+@(qq|126|163)\.com)',y)

for i in ret2:

print(i[0])

#第三种写法:

ret3=re.findall('\w+@(?:qq|126|163)\.com',y)

print(ret3)

2.对于以上的问题我找了一些关于re.findall() 的资料,看看有没有一些合理的解释:

(1)官方文档

(2)发现看了官方文档有些地方还是不够理解Python的re模块中match、search、findall、finditer的区别

(3)或许菜鸟教程的这个解释的更直白

3.在一篇博文里(python re 模块 findall 函数用法简述)找到了一个很好说明问题的例子,摘录在下面了,希望加深“re模块下的findall()函数 ,带括号与不带括号的区别”的理解。

>>> import re

>>> s = "adfad asdfasdf asdfas asdfawef asd adsfas "

>>> reObj1 = re.compile('((\w+)\s+\w+)')

>>> reObj1.findall(s)

[('adfad asdfasdf', 'adfad'), ('asdfas asdfawef', 'asdfas'), ('asd adsfas', 'asd')]

>>> reObj2 = re.compile('(\w+)\s+\w+')

>>> reObj2.findall(s)

['adfad', 'asdfas', 'asd']

>>> reObj3 = re.compile('\w+\s+\w+')

>>> reObj3.findall(s)

['adfad asdfasdf', 'asdfas asdfawef', 'asd adsfas']按以上代码例子讲解:

findall函数返回的总是正则表达式在字符串中所有匹配结果的列表,此处主要讨论列表中“结果”的展现方式,即findall中返回列表中每个元素包含的信息。

1.当给出的正则表达式中带有多个括号时,列表的元素为多个字符串组成的tuple,tuple中字符串个数与括号对数相同,字符串内容与每个括号内的正则表达式相对应,并且排放顺序是按括号出现的顺序。

2.当给出的正则表达式中带有一个括号时,列表的元素为字符串,此字符串的内容与括号中的正则表达式相对应(不是整个正则表达式的匹配内容)。

3.当给出的正则表达式中不带括号时,列表的元素为字符串,此字符串为整个正则表达式匹配的内容。

4.随着研究的深入,发现关于这个问题,已经知乎也有人研究过,而且问题没有我想的那么简单。

>>> a = "one two three four five six"

>>> b = re.findall("(one)|(two)|(three)|(four)|(five)|(six)",a)#加上了"|"号

>>> print(b)

[('one', '', '', '', '', ''), ('', 'two', '', '', '', ''),

('', '', 'three', '', '', ''),('', '', '', 'four', '', ''),

('', '', '', '', 'five', ''),('', '', '', '', '', 'six')]1这个结果是因为按组匹配所以有元组,每个元组都有六个元素。

2而因为是条件匹配,列了六种匹配条件,于是findall匹配六次,结果列表有六个元素。

3又因为每次匹配只能用一种条件,所以按组匹配结果列表中的每个元组只有一组有值而其他均为空。

再在跟官方文档对应一下:Empty matches are includedinthe result.

通过例子,理解起来这句话会容易很多吧。

后来又看到一个例子,发现对大括号里面的{m,},{m,n},{m}这类问题也有盲点,就一并研究了一下:

>>> x = "3 min 46 sec 300 ms"

#分秒毫秒的提取

>>> print(re.findall(r"(\d{0,}) (min|sec|ms)",x))

[('3', 'min'), ('46', 'sec'), ('300', 'ms')] #会不会很方便?

有的时候发现这个表达式很简单,但真正的去做匹配的时候你会发现,好多东西掌握的不够好。有些规则会随着python的不同,结果也会不同,遇到问题的时要多方求证,一方面查看官方文档,另一方面也要找例子来验证,总结规律。Note

Due to the limitation of the current implementation the character following an empty match is not included in a next match, so findall(r'^|\w+', 'two words') returns ['', 'wo', 'words'] (note missed “t”). This is changed in Python 3.7.

#python3.7中的结果

import re

ret=re.findall(r'^|\w+', 'two words')

print(ret)

想了解的更深的话,这篇文章或许也有帮助:

牛刀小试一下吧:

1.把以下文本中的单词全部提取出来

str="hello,world,ha ha"

re.findall('\w+',"hello,workd,ha ha")

re.split(' |,',"hello,workd,ha

2. 匹配用一个空格分隔的任意一对单词,

比如字符串'huang feihong fang shiyu' ,取出的应该是huang feihong 和fang shiyu两个姓名

import re

mystr = 'huang feihong fang shiyu'

print(re.findall('(\w+ \w+)',mystr))

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值