正则表达式
一、定义
regular expression 用于检索、替换、匹配验证字符串。
开源中国正则表达式测试工具:https://tool.oschina.net/regex
一个URL:http://www.baidu.com
正则表达式为
[…]匹配一组字符串,[ab]匹配a,b,ab
[a-zA-Z]匹配英文字母
[^/s]匹配一组非空白字符串
*匹配多个
二、常用匹配规则
字符匹配
\w | 匹配字母、数字、下划线,刚好是代码里要求的字符 |
---|---|
\W | 匹配非字母、数字、下划线的字符 |
\s | space 任意空格,等价于[/r/n/t/f] |
\S | 匹配非空格字符 |
\d | digital匹配数字 |
\D | 匹配非数字字符 |
\n | 匹配换行符 |
\t | 匹配tab |
^ | 匹配一行字符串的开头 |
$ | 匹配一行字符串的结尾 |
数量限制
* | [0,无穷大] |
---|---|
+ | [1,无穷大] |
? | [0,1]问号,有还是没有,所以取值范围为[0,1] |
[] | 匹配一组字符串,[ab],匹配a,b,ab |
[^] | 匹配一组字符串,[^a 匹配不含a 的字符串 |
{n} | 匹配n个前面的表达式 |
{n,m} | 匹配 n 到 m 次由前面正则表达式定义的片段,贪婪方式 |
a|b | 匹配 a或b |
() | 匹配括号内的表达式,也表示一个组 |
. | 匹配除换行符以外的所有字符 |
三、常用修饰符
re.I | 使匹配对大小写不敏感 ignore |
---|---|
re.L | 做本地化识别(local-aware)匹配 |
re.M | 多行匹配,影响^ $ ,Multiline |
re.S | 使.匹配包换换行符在内的字符 |
re.U | 根据Unicode字符集解析字符,影响\w,\W,\b,\B |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解 |
四、代码
import re
#vscode快捷键
# control+b 隐藏,显示右边栏
#control+k+0完全折叠代码
# control+k+j完全展开代码
# control+shift+k 删除当前行
# alt +shift +up/down 复制当前行
#match(正则表达式,content)
def re_match():
'''input:正则表达式,待匹配字符串
output:匹配成功则输出匹配结果对象,负责None
从待匹配字符串的第一个开始匹配'''
content="Hello 123 4567 World_This is a Regex Demo "
result=re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)
print(len(content))
print(result)
#re.Match object有两个函数
#group输出匹配的字符串
print(result.group())
#span()输出匹配范围
print(result.span())
#使用match匹配目标,提取一段数字
#()实际上标记了一个子表达式的开始和结束位置,
# 被标记的每个子表达式会依次对应每一个分组,
# 调用 group()方法传入分组的索引即可获取提取的结果
def match_number():
'目标匹配match匹配一段数字'
content='Hello 949374707 mingyue World'
result=re.match('^Hello\s(\d+)\s(\w+)\s(\w+)',content)
print(result)
print(result.group())
print(result.group(1))
print(result.group(2))
print(result.group(3))
#通用匹配之点心 .*
def general_match():
content='Hello mingyue 12345 this is a regex Demo'
regex='^Hello.*Demo$'
result=re.match(regex,content)
print(result)
print(result.group())
print(result.span())
#.*贪婪匹配尽可能匹配多的字符,.*?非贪婪匹配尽可能匹配少的字符
def greedy_match():
content='hello 123345 what is worth doing is worth doing well'
#贪婪匹配
regex1='^hello(.*)well$'
#非贪婪匹配
regex2='^hello(.*?)'
result1=re.match(regex1,content)
result2=re.match(regex2,content)
print(result1)
print(result1.group())
print(result1.group(1))
print('-----------------')
print(result2)
print(result2.group())
#修饰符的使用
#.*遇到换行符就无法匹配了,how?
def ornament():
content='''i am the sword
in the night'''
regex='^i.*night$'
result=re.match(regex,content,re.S)
print(result)
#转义匹配
def zhuanyi_match():
content='(百度)www.baidu.com'
regex='\(百度\)www\.baidu\.com'
result=re.match(regex,content)
print(result)
print(result.group())
print(result.span())
#search()匹配HTML代码
def search_html():
'''match()从文本的开头开始匹配,
search()搜索整个文本,返回与之匹配的第一个,
否则返回None'''
html='''
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>'''
regex='<li.*?active.*?singer="(.*?)">(.*?)</a>'
result=re.search(regex,html,re.S)
if result:
print(result)
print(result.group())
print(result.group(1))
print(result.group(2))
#findall方法
def re_findall():
'''findall()返回所有匹配的字符
返回结果为列表,列表中的每个元素是元组'''
html='''
<li data-view="4" class="active">
<a href="/3.mp3" singer="齐秦">往事随风</a>
</li>'''
regex='<li.*?active.*?singer="(.*?)">(.*?)</a>'
result=re.findall(regex,html,re.S)
if result:
print(type(result))
print(result)
for i in result:
print(i)
#sub()去掉文本里的全部数字
def re_sub():
'''sub(regex,替换为的字符,content)'''
content='123mingyue456for better you789'
regex='\d+'
content=re.sub(regex,'',content)
print(content)
#compile()
def re_compile():
'''compile将正则表达式编译为一个正则表达式对象
以便重复使用
pattern=re.compile(regex,修饰符)'''
content1='2018-12-26 12:00'
content2='2019-02-06 01:00'
content3='2018-03-28 02:00'
pattern=re.compile('\d{2}:\d{2}')
result1=re.sub(pattern,'',content1)
result2=re.sub(pattern,'',content2)
result3=re.sub(pattern,'',content3)
print(result1)
print(result2)
print(result3)
if __name__ == "__main__":
#re_match()
#match_number()
#general_match()
#greedy_match()
#ornament()
#zhuanyi_match()
#search_html()
#re_findall()
#re_sub()
re_compile()