本文来讲讲看似高大上的正则表达式!
作用简介
学习一样东西,咱们首先要搞明白这东西在什么情况下使用,用来达到什么效果!
否则一上来就讲语法和规则,那基本就晕菜了!
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
这句话太拗口,看个小小的例子就懂了:假设我们现在有一篇文章,是介绍很多不同网站作用的,那我如果想要看看,这篇文章里面介绍了哪些网站,那就可以用到正则表达式。
# 首先引入我们的正则表达式模块 re>>> import re# 然后准备好我们需要搜索的字符串>>> txt = '今天我们来讨论 www.baidu.com 这个网站,这个网站是用来搜索的!'# 这里我们用 re.compile( ) 来设定需要查找的格式,即“正则表达式”。>>> pattern = re.compile(r'www.*com')# 然后我们就可以按照这个格式去文本中搜索啦!>>> result = pattern.findall(txt)# 最后我们打印结果,就看到了我们想要查找的网址!>>> print(result)['www.baidu.com']
首先,这里我们用到 Python 模块就是 re,这个模块就是用来做 “正则表达式” 相关操作滴!
然后用该模块下的 re.compile( ) 函数设定 “模式”!(返回值是一个)re.compile(pattern[, flags])
pattern : 一个字符串形式的正则表达式
flags:可选,表示匹配模式。
这里我们知道,大多数网址都是以 “www” 开头,以 “com” 结尾的,所以我希望按照这个模式去找,找出来的就是网址了!
目的分类
通常有 4 种:定位我们想要寻找的东西所在位置:定位
把指定的东西替换成别的:替换
显示我们想找的具体信息:显示
把对象字符串按照我们想要的进行分割:分割
之前的案例就是属于第 3 种。
案例
一、定位
继续上面的案例
>>> print(re.match('我们', txt, flags=0))None>>> print(re.match('今天', txt, flags=0))
re.match 函数,是用来从开头匹配一个模式,成功就返回位置,比如这里的 ‘今天’ 显示的 span=(0, 2),如果失败,比如这里的 '我们' 就显示 None。re.match(pattern, string, flags=0)
pattern:匹配的正则表达式
string:要匹配的字符串。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等。本文结尾附上了可选标志列表。
还有另外一种寻找位置的方法:
>>> print(re.search('我们', txt, flags=0))>>> print(re.search('今天', txt, flags=0))
re.search 函数 ,扫描整个字符串并返回第一个成功的匹配。re.search(pattern, string, flags=0)
二、替换
继续上面的案例:
>>> import re>>> txt = '今天我们来讨论 www.baidu.com 这个网站,这个网站是用来搜索的!'>>> pattern = re.compile(r'www.*com')>>> new = re.sub(pattern, 'www.google.com', txt, count=0, flags=0)>>> print(new)今天我们来讨论 www.google.com 这个网站,这个网站是用来搜索的!
我们就把里面的网址给替换掉了!
re.sub 函数,用于替换字符串中的匹配项。re.sub(pattern, repl, string, count=0, flags=0)
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 匹配模式。
三、显示
最初案例我们用到的是 re.findall 函数。
re.findall 函数,在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,包含每一个匹配到具体内容,如果没有找到匹配的,则返回空列表。
re.findall(string[, pos[, endpos]])
string:待匹配的字符串。
pos:可选参数,指定字符串的起始位置,默认为 0。
endpos:可选参数,指定字符串的结束位置,默认为字符串的长度。
这里注意:后面的参数是 string,匹配规则需要提前用 re.compile() 函数进行设定。
所以综合起来是这样的:re.compile(pattern[, flags]).findall(string[, pos[, endpos]])
另外一种类似的是 re.finditer 函数。
re.finditer 函数,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
来看案例:>>> txt = '今天我们来讨论 www.baidu.com 和 www.google.com,还有 www.sina.com 吧!'>>> find_txt = re.finditer(r'www.*?com',txt)>>> for each in find_txt:print(each.group())www.baidu.comwww.google.comwww.sina.com
这里需要注意的是用了一个小技巧,就是 .*?,这里的问号 ? 表示的是非贪婪匹配,也就是匹配到了满足条件的即可,不再往后看了,如果改用贪婪模式:
>>> find_txt = re.finditer(r'www.*com',txt)>>> for each in find_txt: print(each.group()) www.baidu.com 和 www.google.com,还有 www.sina.com
这样可就不是我们想要的了,所以大家可以灵活运用得到想要的结果!
四、分割
这里我们用到 re.split 函数。
re.split 函数,按照能够匹配的子串将字符串分割后返回列表。
这其实和 Python 的字符串的 spilt( ) 方法非常类似,但是加上了正则表达式,那么功能肯定是更加强大了!re.split(pattern, string[, maxsplit=0, flags=0])
pattern:匹配的正则表达式。
string:要匹配的字符串。
maxsplit:分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags:正则表达式的匹配方式。
看案例:
>>> txt = 'www.baidu.com 1 www.google.com 2 www.sina.com'>>> re.split('\d', txt)['www.baidu.com ', ' www.google.com ', ' www.sina.com']
模式汇总
这里面的 .*是什么用的呢?这叫做正则表达式的 “模式字符串”,总结语法如下:模式作用^匹配字符串的开头
$匹配字符串的末尾
.匹配任意字符(默认不包括换行符)
[...]匹配一组字符,单独列出
[^...]匹配不在[]中的字符
模式*匹配 0 个或多个该“模式”
模式 +匹配 1 个或多个该“模式”
模式?匹配 0 个或 1 个该“模式”,非贪婪方式
模式{ n}匹配 n 个前该“模式”
模式{ n,}精确匹配 n 个该“模式”
模式{ n,m}匹配 n 到 m 次该“模式”,贪婪方式
a| b匹配 a 或 b
(模式)匹配括号内的“模式”,也表示一个组
(?imx)i, m, x 标志 ,只影响括号中的区域
(?-imx)关闭 i, m, x 标志 ,只影响括号中的区域
(?: 模式)匹配括号内的“模式”,但不表示一个组
(?imx: 模式)i, m, x 标志 ,只影响括号中的区域
(?-imx: 模式)关闭 i, m, x 标志 ,只影响括号中的区域
(?#...)注释
(?= 模式)前向肯定界定符
(?! 模式)前向否定界定符
(?> 模式)匹配的独立模式,省去回溯
\w匹配任意的数字、字母、下划线
\W匹配“非”数字、字母、下划线
\s匹配任意空白字符,等价于 [\t\n\r\f]
\S匹配任意非空字符
\d匹配任意数字,等价于 [0-9]
\D匹配任意非数字
\A匹配字符串开始
\z匹配字符串结束
\Z匹配字符串结束(换行符也算)
\G匹配最后匹配完成的位置
\b匹配一个单词边界(到空格前)
\B匹配非单词边界
\n, \t, \v匹配一个换行符等
\1...\9匹配第 n 个分组的内容
\10匹配第 n 个分组的内容,如未匹配成功,则指的是八进制字符码的表达式
标志汇总修饰符说明re.I使匹配对大小写不敏感
re.L做本地化识别(locale-aware)匹配
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行在内的所有字符
re.U根据 Unicode 字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
re.I | re.M这里用 “或” 即 “|” 来表示同时开启几个标志
正则表达式的学习还是要从实践出发,所以大家如果有搞不定的应用方向,可以留言,我们一起来讨论!