本篇是上一篇 Python 正则表达式、元字符 的补充
正则默认贪婪模式,尽可能多匹配
re模块的方法+元字符组合使用
findall+[]
[]匹配到里面所有的字符,相当于或的关系
从字符串 b 中找出所有属于字符集合 [54h3lk] 的单个字符,并把它们以列表形式返回并打印出来
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'[54h3lk]', b)
print(re1)
使用正则模式 [54h3lk],表示“匹配单个字符,且该字符是 5、4、h、3、l 或 k 中的任意一个”。findall 会返回所有非重叠匹配的子串(这里每次匹配就是一个字符),按在原字符串中出现的顺序放在列表里
解释一下代码中的 r'[54h3lk]' ,在 Python 中,字符串前的 r(或 R)表示这是一个原始字符串(raw string literal)。原始字符串的作用是让反斜杠 \ 不再作为转义字符处理,字符串里所有的反斜杠都按字面意义保留。这对写正则表达式很方便,因为正则里常常要用很多反斜杠(例如 \d、\w、\b、\1 等),用原始字符串可以避免双重转义
补充:匹配是区分大小写的(‘H’ 不等于 ‘h’)
匹配所有的数字
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'[\d]', b)
print(re1)
要是再加个\D,r'[\d\D]'也就是所有值都匹配出来了
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'[\d\D]', b)
print(re1)
findall+''
''里面匹配的是既有又有
匹配所有非空格,\S
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'\S', b)
print(re1)
匹配单词符 \w 即匹配a-z、A-Z、0-9、_
发现+号匹配不到了
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'\w', b)
print(re1)
匹配非单词符 \W
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'\W', b)
print(re1)
这句话如果是 \w\W,就是首先要有字符,还要有非字符才能匹配的到
最后结果是['戏,', '0+', '玩.', 'o ', 'y ', 'e ', 'r!']
戏是字符逗号是非字符,组装在一起'戏,',后面的同理
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'\w\W', b)
print(re1)
如果是 \w\w\W,就是两个单词符和一个非单词符
结果就是['游戏,', '20+', '在玩.', 'lo ', 'my ', 'le ', 'er!']
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re1 = re.findall(r'\w\w\W', b)
print(re1)
*
匹配前一个字符出现0次或者无限次,即可有可无
贪婪模式,尽可能多地去匹配
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re2 = re.findall('.*', b)
print(re2)
运行结果是:['小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!', '']
因为匹配的是出现0次和无线次的,所以最后会有一个空被匹配到
用\d*,就是尽可能匹配多的数字字符
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re2 = re.findall(r'\d*', b)
print(re2)
+
匹配前一个字符出现1次或者无限次,即至少有1次
\D+,匹配非数字字符 1 次或者无限次
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re2 = re.findall(r'\D+', b)
print(re2)
?
匹配前一个字符出现0次或者1次,即要么有1次,要么没有
import re
b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
re2 = re.findall(r'\D?', b)
print(re2)
{}
{m},匹配前一个字符出现m次
import re
# b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
c = 'fffffff'
re1 = re.findall('f{3}', c)
print(re1)
3个3个切割,最后剩1个f,不够三个,切不出来
{m,},匹配前一个字符至少出现m次
import re
# b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
c = 'fffffff'
re1 = re.findall('f{3,}', c)
print(re1)
{m,n},匹配前一个字符出现从m到n次
import re
# b = '小仓在玩2048数独小游戏,每个月有20+天都在玩...hello my little hamster!!'
c = 'fffffff'
re1 = re.findall('f{3,4}', c)
print(re1)
最后剩一个,既不符合3也不符合4,最后会出来一个4一个3
代表边界的元字符
^
匹配字符串开头
import re
a = 'abcdefg'
re1 = re.findall('^abc', a)
re2 = re.findall('^bcd', a)
print(re1)
print(re2)
$
匹配字符串结尾
import re
a = 'abcdefg'
re1 = re.findall('def$', a)
re2 = re.findall('efg$', a)
print(re1)
print(re2)
^$ 组合在一起使用:
import re
a = 'abcdefg'
re1 = re.findall('^def$', a)
re2 = re.findall('^efg$', a)
re3 = re.findall('^abcdefg$', a)
re4 = re.findall('^.*$', a)
print(re1)
print(re2)
print(re3)
print(re4)
分组匹配
|
匹配左右任意一个表达式,相当于或
左边一个表达式,右边一个表达式。满足左边或者右边的就可以匹配上
(ab)
将括号中的字符作为一个分组
import re
a = '<img src = "xiaomeimei.jpg" alt="这是图片"><img src = "zhongmeimei.jpg" alt="这是图片"><img src = "dameimei.jpg" alt="这是图片">'
re1 = re.findall('src = (.*?jpg)', a)
print(re1)
贪婪和非贪婪
正则默认都是用贪婪模式去匹配数据的,就是尽可能多的匹配符合要求的数据,
在非贪婪模式下,始终找最短匹配
a = '<img src = "xiaomeimei.jpg" alt="这是图片">' b = '<html>000</html><td>ddd</td>' print(re.findall(r'<.*>',b))# 贪婪 print(re.findall(r'<.*?>',b))# 加上?变成非贪婪 print(re.findall(r'-(\d+)(.+-)','-123456789-')) print(re.findall(r'-(\d+?)(.+-)','-123456789-'))