Python常用标准库之正则表达式
Python常用标准库之正则表达式
- 1.re模块常用函数
- 1.1 匹配对象以及group()和groups()方法
- 1.2 match()与search():匹配单个目标
- 1.3 findall():匹配多个相同目标
- 1.4 split():分割字符串
- 1.5 sub()与subn():搜索替换
- 2.特殊符号和字符
- 2.1 管道符号“|”:匹配多个不同字符串
- 2.2 点号:匹配任意单个字符
- 2.3 表示字符集的特殊字符
- 2.4 贪婪匹配与非贪婪匹配
- 2.5 圆括号:分组匹配
- 3.常用正则表达式
- 3.1 校验数字的表达式
- 3.2 校验字符的表达式
- 3.3 特殊需求表达式
- 4.正则表达式在线测试网站
- 在线测试网站一:[https://tool.lu/regex/\](https://tool.lu/regex/)
- 在线测试网站二:[https://tool.oschina.net/regex\](https://tool.oschina.net/regex)
- 在线测试网站三:[https://c.runoob.com/front-end/854\](https://c.runoob.com/front-end/854)
1.re模块常用函数
Python通过内置的标准库 re 模块来支持正则表达式,通过 re 模块自带的函数来进行正则搜索或匹配,帮助我们找到想要的文本内容。
re 模块的核心函数和方法如下:
1.1 匹配对象以及group()和groups()方法
当处理正则表达式时,除了正则表达式对象之外,还有另一个对象类型:匹配对象。这些是成功调用match()或者search()返回的对象。匹配对象有两个主要的方法:group()和groups()。
group()要么返回整个匹配对象,要么根据要求返回特定子组。groups()则仅返回一个包含唯一或者全部子组的元组。如果没有子组的要求,那么当group()仍然返回整个匹配时,groups()返回一个空元组。
1.2 match()与search():匹配单个目标
match()函数试图从字符串的起始部分对模式进行匹配。
如果匹配成功,就返回一个匹配对象;如果匹配失败,就返回None,匹配对象的group()方法能够用于显示那个成功的匹配。
search()的使用方式与match()完全一致,不同之处在于search()可以搜索在文本任意位置第一次出现的匹配目标。
如果搜索到成功的匹配,就会返回一个匹配对象;否则,返回None。
输入:
import re
# match
result1 = re.match(r'python', 'pythonhello').group()
# search
result2 = re.search(r'python', 'hellopython').group()
print(result1)
print(result2)
输出:
python
python
1.3 findall():匹配多个相同目标
查找字符串中多次出现的目标,结果以列表的形式返回,不需要group()方法。
输入:
import re
# findall()
result3 = re.findall(r'python', 'python hello python')
print(result3)
输出:
['python', 'python']
1.4 split():分割字符串
split函数可以把一段字符串分割成多个字符,把分割的结果以列表的形式返回。
输入:
import re
# split()
text = "hello\nworld\npython"
pat = '\n'
result4 = re.split(pattern=pat, string=text)
print(result4)
输出:
['hello', 'world', 'python']
1.5 sub()与subn():搜索替换
sub()和subn()都是将某字符串中所有匹配正则表达式的部分进行某种形式的替换,但subn()还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
案例一:
输入:
import re
# sub()与subn()
text = "hello\nworld\npython"
pat = '\n'
replace = ","
result5 = re.sub(pattern=pat, repl=replace, string=text)
result6 = re.subn(pattern=pat, repl=replace, string=text)
print(result5)
print(result6)
输出:
hello,world,python
('hello,world,python', 2)
案例二:
输入:
text = "<div>\
<p>\n岗位\n职责:</p>\
<p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>\
<p><br></p>\
<p>必备要求:</p>\
<p>良好的自我驱动力和职业素养,工作积极主动、结果导向</p>\
<p> <br></p>\
<p>技术要求:</p>\
<p>1、一年以上 Python 开发经验,掌握面向对象分析和设计,了解设计模式</p>\
<p>2、掌握HTTP协议,熟悉MVC、MVVM等概念以及相关WEB开发框架</p>\
<p>3、掌握关系数据库开发设计,掌握 SQL,熟练使用 MySQL/PostgreSQL 中的一种<br></p>\
<p>4、掌握NoSQL、MQ,熟练使用对应技术解决方案</p>\
<p>5、熟悉 Javascript/CSS/HTML5,JQuery、React、Vue.js</p>\
<p> <br></p>\
<p>加分项:</p>\
<p>大数据,数理统计,机器学习,sklearn,高性能,大并发。</p>\
\
</div>"
res = re.sub(r'<[^>]*>| |\n', '', text)
print(res)
输出:
岗位职责:完成推荐算法、数据统计、接口、后台等服务器端相关工作必备要求:良好的自我驱动力和职业素养,工作积极主动、结果导向技术要求:1、一年以上 Python 开发经验,掌握面向对象分析和设计,了解设计模式2、掌握HTTP协议,熟悉MVC、MVVM等概念以及相关WEB开发框架3、掌握关系数据库开发设计,掌握 SQL,熟练使用 MySQL/PostgreSQL 中的一种4、掌握NoSQL、MQ,熟练使用对应技术解决方案5、熟悉 Javascript/CSS/HTML5,JQuery、React、Vue.js加分项:大数据,数理统计,机器学习,sklearn,高性能,大并发。
2.特殊符号和字符
正则表达式由丰富的符号组成,主要分为两类,一类是普通字符,一类是元字符。
普通字符指只具有自己本身原始含义,不具备其他功能或含义的字符, 如所有大写和小写字母、所有数字和一些其他符号。
元字符指在正则表达式中具有特殊含义的专用字符,是除了自己本身的原始含义,还具备某些功能或具有某一类属性、意义的字符,如\d代表代表匹配任何十进制数字。
2.1 管道符号“|”:匹配多个不同字符串
管道符号 | 表示择一匹配,即管道符号左右任何一个都能匹配。
输入:
import re
# 匹配hello、你好
text = "hello\nworld\npython,你好"
pat = "hello|你好"
result = re.findall(pat, text)
print(result)
输出:
['hello', '你好']
2.2 点号:匹配任意单个字符
点号或句点符号(.)匹配除了换行符 \n 以外的任何字符。
输入:
import re
# 匹配所有一个以“刘”开始的名称
text = "hello 胡月 刘易 刘亦 王二狗 刘X 刘*"
pat = "刘."
result = re.findall(pat, text)
print(result)
输出:
['刘易', '刘亦', '刘X', '刘*']
2.3 表示字符集的特殊字符
通过中括号包含的内容称为字符集,常用字符集如下:
[a-z] :表示从小写的a到z的26个字母的字符集;
[A-Z] :表示从大写的A到Z的26个字母的字符集;
[0-9] :表示从0到9的10个数字的字符集;
\w:表示匹配任何字母数字字符,包含下划线,与[A-Za-z0-9_]相同;
\d :表示匹配任何十进制数字,与[0-9]一致;
[a-zA-Z0-9_]:表示包含所有的26个字母(含大小写)、数字(从0到9的10个数字)以及下划线(_)的字符集。
输入:
# 找出所有以.com结尾的、合法的邮箱地址
# 合法邮箱要求@前面和后面部分(除了.com外)只能包含字母、数字、下划线
import re
text = "htt_yfe@126.com, grd432.@qq.com, assdf@yy.coxx, mnbgfd123@good.com"
# 方法一,匹配规则:[a-zA-Z0-9_]+@[a-zA-Z0-9_]+\.com
pat1 = '[a-zA-Z0-9_]+@[a-zA-Z0-9_]+\.com'
result1 = re.findall(pat1, text)
# 方法二,匹配规则:\w+@\w+\.com
pat2 = '\w+@\w+\.com'
result2 = re.findall(pat2, text)
print(result1)
print(result2)
输出:
['htt_yfe@126.com', 'mnbgfd123@good.com']
['htt_yfe@126.com', 'mnbgfd123@good.com']
2.4 贪婪匹配与非贪婪匹配
在使用正则做搜索匹配时,有时候我们需要匹配尽可能多的数据,有时候又需要匹配尽可能少的数据,这时需要分别用到贪婪模式和非贪婪模式:
- 贪婪模式:总是尝试匹配尽可能多的字符(Python默认);
- 非贪婪模式:总是尝试匹配尽可能少的字符;
当我们在使用下表中 *,+,?,{N},{M,N} 这5个特殊字符去匹配字符串或文本时,默认会尽可能多(贪婪)的去匹配符合条件的字符,如果在它们后面加上 ?,则表示尽可能少(非贪婪)的去匹配符合条件的字符。这5个特殊字符的作用如下表:
输入:
# 贪婪匹配与非贪婪匹配
import re
text = "<div>test1</div>test2</div>"
pat1 = "<div>.*</div>" # 贪婪模式
pat2 = "<div>.*?</div>" # 非贪婪模式
result1 = re.search(pat1, text).group()
result2 = re.search(pat2, text).group()
print(result1)
print(result2)
输出:
<div>test1</div>test2</div>
<div>test1</div>
2.5 圆括号:分组匹配
在写爬虫或做数据处理时,通常网页文本内容比较大,其中有一些内容可以通过相同的规则去匹配,但是却不连续,那么我们可以通过分组去匹配,在后面引用前面的分组匹配规则,不需要重复多次写相同的规则,这样也比较符合编程里面代码复用的思想。
案例一:
输入:
# 利用分组找出文本中的: <ul><li>Hello,这是测试网页。</li></ul>
import re
text = "cnn<a><ul><li>Hello,这是测试网页。</li></ul></div>"
pat = '<(?P<group1>\w+)>.*</(?P=group1)>'
result = re.search(pat, text).group()
print(result)
输出:
<ul><li>Hello,这是测试网页。</li></ul>
思路:
案例二:
输入:
import re
s = "This is a number 234-235-22-423"
r = re.match(r'(.+?)(\d+-\d+-\d+-\d+)', s)
print(r.group(1))
print(r.group(2))
输出:
This is a number
234-235-22-423
3.常用正则表达式
3.1 校验数字的表达式
数字:^[0-9]*$
n位的数字:^\d{
n}$
至少n位的数字:^\d{
n,}$
m-n位的数字:^\d{
m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(\.[0-9]{
1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{
1,2})$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(\.[0-9]{
2})?$
有1~3位小数的正实数:^[0-9]+(\.[0-9]{
1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){
1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
3.2 校验字符的表达式
汉字:^[\u4e00-\u9fa5]{
0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{
4,40}$
长度为3-20的所有字符:^.{
3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{
3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{
2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+
3.3 特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{
0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{
0,62})+\.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{
8}$
电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{
3,4}-)|\d{
3.4}-)?\d{
7,8}$
国内电话号码(0511-4405222、021-87888822):\d{
3}-\d{
8}|\d{
4}-\d{
7}
电话号码正则表达式(支持手机号码,3-4位区号,7-8位直播号码,1-4位分机号): ((\d{
11})|^((\d{
7,8})|(\d{
4}|\d{
3})-(\d{
7,8})|(\d{
4}|\d{
3})-(\d{
7,8})-(\d{
4}|\d{
3}|\d{
2}|\d{
1})|(\d{
7,8})-(\d{
4}|\d{
3}|\d{
2}|\d{
1}))$)
身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{
15}$)|(^\d{
18}$)|(^\d{
17}(\d|X|x)$)
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{
4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{
5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在 8-10 之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{
8,10}$
强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{
8,10}$
日期格式:^\d{
4}-\d{
1,2}-\d{
1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
钱的输入格式:
有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{
2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{
1,2})?$
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{
1,3}(,[0-9]{
3})*(.[0-9]{
1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{
1,3}(,[0-9]{
3})*)(.[0-9]{
1,2})?$
备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? /> ( 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{
4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{
5}(?!\d) (中国邮政编码为6位数字)
IPv4地址:((2(5[0-5]|[0-4]\d))|[0-1]?\d{
1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{
1,2})){
3}
4.正则表达式在线测试网站
1. 在线测试网站一:https://tool.lu/regex/
2. 在线测试网站二:https://tool.oschina.net/regex
3. 在线测试网站三:https://c.runoob.com/front-end/854
参考地址:
https://c.runoob.com/front-end/854
还没有评论,来说两句吧...