正则表达式
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
-
需要引入内置模块re
-
缺点:效率低下,能用字符串方法完成尽量使用字符串的方法
-
优点:编码简单
1.为什么使用正则表达式
-
使用场景
-
敏感词过滤
-
手机、邮箱等验证
-
爬虫
2.正则表达式的组成
-
原子
组成正则表达式的最小单位,任何字符都可以
原子 | 含义 | 原子 | 含义 |
---|---|---|---|
\d | 0-9中任何一个字符 [0-9] | \w | 0-9a-zA-Z_的中任何一个字符 [0-9a-zA-Z_] |
\D | 非0-9中的任何一个字符 [^0-9] | \W | 非0-9a-zA-Z_的中任何一个字符[^0-9a-z_A-Z] |
\s | \n\r\t 空格 | . | 代表除\n之外的任何字符 |
\S | 非\n\r\t 空格中任何一个字符[^\n\t\r ] | \b | 词边界 |
[] | 自己创建的原子表,[0-4]代表0-4中任何一个字符 | \B | 非词边界 |
[^] | 排除原子表中的字符 | \A | 字符串开始 |
^ | 行首;在原子表中表示排除 | \Z | 字符串的结尾 |
$ | 行结尾 | - | 表示域,0-9就表示0到9所有数字字符 |
-
元字符
元字符能够增强原子的描述能力
元字符 | 含义 | 元字符 | 含义 |
---|---|---|---|
{} | 表示重复前一个原子的次数 | * | 重复0次或多次 {0,} |
{m} | 表示重复前一个原子的m次 | + | 至少出现1次 {1,} |
{m,n} | 表示重复前一个原子的最少m次,最多n次 | ? | 出现0次或1次 {0,1} |
{m,} | 表示重复前一个原子的最少m次 | *?,+? | 取消贪婪 |
() | 改变优先级,取子元素 | x|y | 表示匹配x或者y |
-
模式修正符
修饰符 | 含义 | 修饰符 | 含义 |
---|---|---|---|
re.S | 使.匹配所有字符 | re.I | 不区分大小写 |
re.L | 本地化识别 | re.M | 多行匹配 |
re.U | 根据Unicode字符集解析字符,会影响\b、\B、\w、\W |
-
边界字符
字符 | 含义 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
-
匹配分组
字符 | 含义 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?P) | 分组起别名 |
(?P=name) | 引用别名为name分组匹配到的字符串 |
注意:
-
模式字符串一定要使用原字符串,也就是用r开头的字符串。r'www'
-
严格区分大小写
-
如果正则表达式中有{,},[,],-,?,*,|^,$,.等做普通字符,则要将其转义
3. 正则常用方法
compile():将正则表达式模式编译成正则表达式对象,其 match() 和 search() 方法可用于匹配
当我们使用正则表达式时,re模块会干两件事
1、编译正则表达式,如果正则表达式本身不合法,会报错
2、用编译后的正则表达式去匹配对象
编译正则表达式使用compile
原型:re.compile(pattern, flags=0)
参数:pattern 模式
flags 模式修正符
re_telephon = re.compile(r"^1(([3578]\d)|(47))\d{8}$") #编译,返回正则对象
print(re_telephon.match("13600000000")) #
prog = re.compile('\d{2}') # 正则对象
prog.search('100abc') # 正则对象调用search获取匹配
re.match() :从字符串起始位置匹配一个模式,如果从起始位置匹配没有匹配成功,则返回None
原型:re.match(pattern,string,flags=0)
参数:patter 模式
string 要匹配的字符串
flag 模式修正符
返回值: 匹配成功返回一个Match object,失败返回None
print(re.match(r'www','www.baidu.com'))
print(re.match(r'www','http:///www.baidu.com')) #None
print(re.match(r'www','cctv.www.baidu.com')) #None
# 结合分组使用,进行标签匹配
str = "<span><h1>hello world!</h1></span>"
pattern = r"<(.+)><(.+)>.*</\2></\1>"
result = re.match(pattern, str)
print(result.groups())
re.search() : 顺序扫描字符串,找到第一个匹配项则结束。
原型:re.search(pattern, string, flags=0)
参数:patter 模式
string 要匹配的字符串
flag 模式修正符
返回值:匹配成功,返回match object,否则返回None
print(re.search(r'll','hello'))
print(re.search(r'll','heLLo',re.I))
#读取字符串中文章浏览次数
str = "浏览次数为: 8098"
pattern = r"\d+"
result = re.search(pattern, str)
print(result.group())
re.group()和re.groups()
用于提取子元素,模式中一个括号就是一个子元素,group和groups只能在match和search方法里使用,通过返回的match object获取子元素。在模式串和sub和subn中的替换字符串中可以使用\1,\2,\3....来引用子元素
m = re.match(r"(\d{3})-(\d{8})", "010-53247654")
#使用序号获取对应组的信息,group(0)一直代表的原始字符串
print(m.group(0))
print(m.group(1))
print(m.group(2))
#查看匹配的各组的情况
print(m.groups())
# 匹配出0-100之间的数字
pattern = r"0$|100$|[1-9]\d{0,1}$"
#测试数据为0,3,27,100,123
result = re.match(pattern, "27")
print(result.group())
re.findall() : 扫描整个字符串,并返回结果列表
原型:findall(pattern, string, flags=0)
参数:patter: 匹配的正则表达式
string: 要匹配的字符串
flags:模式修正符
返回值:如果匹配成功返回一个列表,包含了所有匹配项,失败返回空列表
print(re.findall(r'oo','kksdkoosdflsdfooksdfsdoOppppweOo',re.I)) #['oo', 'oo', 'oO', 'Oo']
#findall方法取得所有满足的查找
str = "<div>hello</div>world<div>hello宋宋</div>"
pattern = r"\w+</h1>"
result = re.findall(pattern, str)
print(result)
re.split() :用模式做分隔符,将字符串分隔,返回分隔列表,如果模式加上括号,则分隔符会被保留
通过出现模式来拆分字符串。如果在pattern中使用了捕获括号,那么模式中所有组的文本也将作为结果列表的一部分返回。如果maxsplit不为零,则最多会发生maxsplit分割,并将字符串的其余部分作为列表的最后一个元素返回。
原型:split(pattern, string,maxsplit=0,, flags=0)
参数:patter: 匹配的正则表达式
string: 要匹配的字符串
maxsplit 匹配次数,0不限制次数
flags:模式修正符
# 遇到数字或者逗号或者分号,就分割
print(re.split(r'\d|,|;','w1w2w3w,w;w')) #['w', 'w', 'w', 'w', 'w', 'w']
# \W表示非0-9a-zA-Z_的中任何一个字符,则分隔。
print(re.split(r'\W+','Words,words,words.')) # ['Words', 'words', 'words', '']
# 遇到字母则分隔,忽略大小写
re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE) # ['0','3','9']
re.sub和re.subn() :在目标字符串中以正则表达式的规则匹配字符串,再把他们替换成指定的字符串。可以指定替换的次数, 如果 不指定,替换所有的匹配字符串
sub(pattern, repl, string, count=0)
subn(pattern, repl, string, count=0)
参数:
pattern: 正则表达式(规则)
repl: 指定的用来替换的字符串
string: 目标字符串
count: 最多替换次数
区别:前者返回一个替换后的字符串,后者返回一个元组,第一个元素替换后的字符串,
第二个元素表示被替换的次数
print(re.sub(r"(beautiful)", "graceful", "songsong is beautiful girl"))
print(re.subn(r"(beautiful)", "graceful", "songsong is beautiful girl"))
# 结果:
# songsong is graceful girl
# ('songsong is graceful girl', 1)