本文以面试题的方式介绍re模块的部分用法
groups()
# 1.字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
re.match('www', 'www.runoob.com')
a.group() # 'www'
a.group(0) # 'www' 等价于a.group()
a.groups() # ()
a.group(1) # IndexError: no such group
# 2.用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
re.match('[www]', 'www.runoob.com') # [www]]等价于[w],一般不会这样写
a.group() # 'w'
a.group(0) # 'w' 等价于a.group()
a.groups() # ()
a.group(1) # IndexError: no such group
# 3.(re)对正则表达式分组并记住匹配的文本
re.match('(www)', 'www.runoob.com')
a.group() # 'www'
a.group(0) # 'www' 等价于a.group()
a.groups() # ('www',)
a.group(1) # 'www'
# 4.分多组匹配
a = re.match( r'(\w*)\.(\w*)\.(\w*)', 'www.runoob.com')
a.group() # 'www.runoob.com'
a.group(0) # 'www.runoob.com' 等价于a.group()
a.groups() # ('www', 'runoob', 'com')
a.group(1) # 'www'
a.group(2) # 'runoob'
a.group(3) # 'com'
a.group(4) # IndexError: no such group
# 5.贪婪模式(此处匹配最后一个.之前所有字符串)
a = re.match( r'(.*)\..*', 'Www.runoob.com', re.I)
a.group() # 'www.runoob.com'
a.groups() # ('www.runoob',)
# 6.非贪婪模式*?(此处匹配第一个.之前所有字符串)
a = re.match( r'(.*?)\..*', 'Www.runoob.com', re.I)
a.group() # 'www.runoob.com'
a.groups() # ('www',)
# 7.'(?P...)' 分组匹配
s = '1102231990xxxxxxxx'
a= re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',s)
a.group() # '1102231990'
a.groups() # ('110', '223', '1990')
a.groupdict() # {'province': '110', 'city': '223', 'born_year': '1990'}
正则表达式匹配中,(.)和(.?)匹配区别?
- (.*)是贪婪匹配,会把满足正则的尽可能多的往后匹配
- (.*?)是非贪婪匹配,会把满足正则的尽可能少匹配
re.split
s=“info:xiaoZhang 33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]
import re
s="info:xiaoZhang 33 shandong"
# |表示或,根据冒号或者空格切分
re.split(r':| ',s) # ['info', 'xiaoZhang', '33', 'shandong']
re.search
<div class="nam">中国</div>
,用正则匹配出标签里面的内容(“中国”),其中class的类名是不确定的
s='<div class="nam">中国</div>'
a=re.search(r'<div class=".*">(.*)</div>',s)
a.groups() # ('中国',)
re.sub
字符串a = “not 404 found 张三 99 深圳”,每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"
a = "not 404 found 张三 99 深圳"
b=re.sub(r'[0-9a-zA-Z]+\s','',a) # 将任意字母或数字且后面带有空白符的字串替换为''
# '张三 深圳'
a=“张明 98分”,用re.sub,将98替换为100
>>> a="张明 98分"
>>> b=re.sub(r'\d+','100',a)
>>> b
'张明 100分'
替换的参数可以是一个函数
# 将匹配的数字乘以 2
s = 'A23G4HFD567'
def double1(matched):
value = int(matched.group(1))
return str(value*2)
print(re.sub('(\d+)', double1, s)) # A46G8HFD1134
# 或利用'(?P...)' 分组匹配
def double2(matched):
value = int(matched.group('value'))
return str(value * 2)
print(re.sub('(?P<value>\d+)', double2, s)) # A46G8HFD1134
# lambda
print(re.sub('(\d+)', lambda x:str(int(x.group(1))*2),s)) # A46G8HFD1134
# 提取数字:用数字替换查找的文本 如:找到'A23',组内容为'23',用'23'替换'A23';然后继续下一次操作
>>> a=re.sub(r'[a-zA-Z]*(\d+)',lambda x:x.group(1),s)
>>> a
234567
re.findall
正则匹配,匹配日期2018-03-20
url=‘https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462’
>>> url='https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462'
>>> a=re.findall(r'\d{4}\-\d{2}\-\d{2}',url)
>>> a
['2018-03-20', '2018-03-20'] # findall返回的是list
re.compile
正则匹配中文
>>> title = '你好,hello,世界!'
>>> p = re.compile(r'[\u4e00-\u9fa5]+') # 或re.compile(r'[一-龥]+') 这两个unicode值正好是Unicode表中的汉字的头和尾。
>>> p.findall(title)
['你好', '世界']
正则re.complie作用?
re.compile是将正则表达式编译成一个对象,加快速度,并重复使用
\1…\9 匹配第n个分组的内容
正则表达式匹配出<html><h1>www.itcast.cn</h1></html>
>>> label='<html><h1>www.itcast.cn</h1></html>'
>>> a=re.match(r'<(\w*)><(\w*)>.*</\2></\1>',label) # \2匹配第2组的内容 \1匹配第1组的内容
>>> a.group()
'<html><h1>www.itcast.cn</h1></html>'
>>> a.groups()
('html', 'h1')
>>> label='<html><h1>www.itcast.cn</h2></html>'
>>> a=re.match(r'<(\w*)><(\w*)>.*</\2></\1>',label)
>>> a.group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
其他正则排序面试题
A. 有字符串 A = ‘a33aa2a3aa5aa6aaa3aaa7aaa8aaa4’
求出所有含有一个或者多个 ‘a’ 子串加数字子串的子字符串(如:‘a33’, 'aa2’等),并排序,排序要求:
(1)含 ‘a’ 少的子字符串放在前,含 ‘a’ 多的子字符串放在后面;
(2)含 ‘a’ 子串数相同的再比较子串后面的数字大小,按从大到小排序。
>>> A = 'a33aa2a3aa5aa6aaa3aaa7aaa8aaa4'
>>> l = re.findall(r'a+\d+', A)
>>> sorted(l,key=lambda x:(x.count('a'), -int(x[x.count('a'):])))
['a33', 'a3', 'aa6', 'aa5', 'aa2', 'aaa8', 'aaa7', 'aaa4', 'aaa3']
sorted() 中key的排序规则可以有多个,比如:
1)x.count(‘a’) 以字母 a 的个数大小排序;
2)-int(x[x.count(‘a’):]) 以字母 a 后面数字的大小排序,加负号则按逆序排列;
3)默认从小到大排序;
B. 去除以下html文件中的标签,只显示文本信息
s = """<div>\
<p>岗位职责:</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> """
a=re.sub(r'</?\w+>','',s)
C. 将以下网址提取出域名
url = 'http://www.interoem.com/messageinfo.asp?id=35'
a=re.match(r'http[s]?://.+?/',url)
a.group() # http://www.interoem.com/
url = 'http://www.interoem.com/messageinfo.asp?id=35,https://3995503.com/class/class09/news_show.asp?id=14,http://lib.wzmc.edu.cn/news/onews.asp?id=769'
a=re.findall(r'(http[s]?://.+?/)', url) # ['http://www.interoem.com/', 'https://3995503.com/', 'http://lib.wzmc.edu.cn/']
D. 提取出如下字符串中的单词
>>> s='hello world ha ha'
>>> s.split(' ')
['hello', 'world', 'ha', 'ha']
>>> a=re.findall(r'\b[a-zA-Z]+\b', s)
['hello', 'world', 'ha', 'ha']
\b
:匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 'er