Python基础24_正则表达式,re模块,
一. 正则表达式
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式由普通字符和元字符组成, 普通字符包含大小写字母, 数字. 在匹配普通字符的时候我们直接写就可以了
元字符是正则表达式的灵魂
1. 字符组
字符组用[]括起来, 在[]中的内容会被匹配
[a-zA-Z0-9] 表示所有的数字字母
2. 简单元字符
. 匹配除换行符之外的任意字符
\w 匹配数字或字母或下划线
\s 匹配任意的空白符
\d 匹配数字
\n 匹配一个换行符
\t 匹配一个制表符
\b 匹配一个单词的边界
^ 匹配字符串的开始
$ 匹配字符串的结尾
\W 匹配非字母或数字或下划线
\D 匹配非数字
\S 匹配非空白符
a|b 匹配字符a或字符b
() 匹配括号内的表达式, 也表示一个组
[...] 匹配字符组中的字符
[^...] 匹配除了字符组中字符的所有字符
3. 量词
* 重复0次或更多次
+ 重复1次或更多次
? 重复0次或1次
{n} 重复n次
{n, } 重复n次或更多次
{n, m} 重复n次到m次
4. 惯性匹配和贪婪匹配
* + {} 都属于贪婪匹配, 就是尽量多的匹配到结果
在使用.*后再加?就是尽可能的少匹配, 表示惰性匹配
.*?x 表示找到下一个x为止
5. 分组
使用()进行分组
6. 转义
在python中, 无论是正则表达式还是待匹配的内容, 都是以字符串的内容出现的
r"\\n" 表示正则的r"\n"
二. re模块
import re
python提供的一套关于处理正则表达式的模块
1. findall() 查找所有, 返回list
result = re.findall("\d", "asdf123asdf456")
print(result)
# ['1', '2', '3', '4', '5', '6']
2. search() 进行匹配, 但是如果匹配到第一个结果, 就会返回该结果, 匹配不到则返回None
result = re.search("\d", "asdf123asdf456")
print(result.group())
# 1
3. match() 只能从字符串的开头进行匹配, 匹配不到则返回None
result = re.match("\d", "asdf123asdf456")
print(result.group())
# AttributeError: 'NoneType' object has no attribute 'group'
4. finditer() 和findall用法相似, 但返回的是迭代器
result = re.finditer("\d+", "asdf123asdf456")
print(result)
<callable_iterator object at 0x029A28D0>
for el in result:
print(el.group())
# 123
# 456
5. split() 用多个元素去切割
ret = re.split("[ab]", "qweabdfdadffbffs")
print(ret)
# ['qwe', '', 'dfd', 'dff', 'ffs']
6. sub() 替换
ret = re.sub(r"\d+", "_sb_", "faf123fsfs456dsf")
print(ret)
# faf_sb_fsfs_sb_dsf
7. subn() 替换, 替换了多少次
ret = re.subn(r"\d+", "_sb_", "faf123fsfs456dsf")
print(ret)
# ('faf_sb_fsfs_sb_dsf', 2)
8. compile() 将正则表达式编译成一个正则表达式对象
obj = re.compile(r"\d{3}")
ret = obj.search("sfdaf13321fasf123fffsaf")
print(ret.group())
# 133
9. 爬虫的一个重点, 分组命名
result = re.finditer("姓名: (?P<name>.*?), 爱好: (?P<hobby>.*?),", "姓名: 宝宝, 爱好: 女, 年龄: 18")
for el in result:
print(el.group("name"), el.group("hobby"))
# 宝宝 女
坑1 分组合取消分组权限
这里因为findall会优先把匹配结果组里的内容返回, 如果想要匹配结果, 取消权限即可
ret = re.findall("www.(baidu|oldboy).com", "www.oldboy.com")
print(ret)
# ['oldboy']
?: 相当于取消了分组的权限
ret = re.findall("www.(?:baidu|oldboy).com", "www.oldboy.com")
print(ret)
# ['www.oldboy.com']
坑2 split切割 分组加()的结果
# 坑2
ret = re.split("\d+", "asf3faf4asdf")
print(ret)
# ['asf', 'faf', 'asdf']
ret = re.split("(\d+)", "asf3faf4asdf")
print(ret)
# ['asf', '3', 'faf', '4', 'asdf']
在匹配部分加上()后切出来的结果是不同的
没有()则没有保留所匹配的项, 有()则保留了匹配的项
这个在某些需要保留匹配部分的使用过程是非常重要的