目录
- 知识点1 正则的目的
- 知识点2 正则表达式的优缺点
- 知识点3 re模块
- 知识点4 re模块基本用法-raw
- 知识点5 re模块基本用法-match对象
- 知识点6 re模块基本用法-findall finditer
- 知识点7 re模块基本用法-sub
- 知识点8 re模块基本用法-compile
- 知识点9.1 基本正则匹配-区间
- 知识点9.2 基本正则匹配-或匹配
- 知识点9.3 基本正则匹配-取反
- 知识点9.4 基本正则匹配-任意字符(占位符)
- 知识点9.5 基本正则匹配-快捷方式
- 知识点9.6 基本正则匹配-开始与结束
- 知识点10 正则重复-通配符
- 知识点10.1 正则重复-通配符
- 知识点10.2 正则重复-通配符
- 知识点10.3 正则重复-通配符
- 知识点10.4 正则重复-通配符
- 知识点11 基本正则匹配-贪婪与非贪婪模式
博客cpen_web
知识点1 正则的目的
正则的目的
·数据挖掘 # 注:查找IP地址那题
从一大堆文本中找到一小堆文本时。如,从文本是寻找email, ip, telephone等
·验证 # 注:邮箱、用户名、密码
使用正则确认获得的数据是否是期望值。如,email、用户名是否合法等
·非必要时慎用正则,如果有更简单的方法匹配,可以不使用正则
#注:正则表达式非常耗性能
·指定一个匹配规则,从而识别该规则是否在一个更大的文本字符串中。
·正则表达式可以识别匹配规则的文本是否存在
·还能将一个规则分解为一个或多个子规则,并展示每个子规则匹配的文本
知识点2 正则表达式的优缺点
正则表达式的优缺点
优点:提高工作效率、节省代码
缺点:复杂,难于理解
知识点3 re模块
re模块
从文本中匹配某些子串。
·官方文档:https://docs.python.org/3/library/re.html
·安装: python标准库,无需要安装
re模块基本用法-search
match与search: 查找第一个匹配
re.search
·查找匹配项
·接受一个正则表达式和字符串,并返回发现的第一个匹配。
·如果完全没有找到匹配,re.search返回None
re模块基本用法-match
match与search: 查找第一个匹配
re.match
·从字符串头查找匹配项
·接受一个正则表达式和字符串,从主串第一个字符开始匹配,并返回发现的第一个匹配。
·如果字符串开始不符合正则表达式,则匹配失败,re.match返回None
#查找匹配
#1.search 和 match
#search 是接收一个正则表达式和字符串并返回发现的第一个匹配
#march 从字符串头查找匹配
#只匹配字符串的开始
示例
>>> import re
>>> dir(re) # 注:查看属性
>>> help(re.search) # 注:查看帮助文档
search(pattern, string, flags=0) # 注:下标从0开始
>>> re.search("sanchuang","hello world, this is sanchuang") # 注:“sanchuang是模块”
<_sre.SRE_Match object; span=(21, 30), match='sanchuang'> # 注:返回的是match对象
>>> re.search("sanchuang","hello world, this is") # 注:没有返回,是None
>>> result = re.search("sanchuang","hello world, this is")
>>> print(result) # 注:没有返回,是None
None
>>> re.match("sanchuang","hello world, this is sanchuang")
>>> re.match("sanchuang","sanchuang,hello world, this is") # 注:match匹配开头位置第一个
<_sre.SRE_Match object; span=(0, 9), match='sanchuang'>
#注:search在任意位置匹配第一个
#注:match在开头位置匹配第一个
知识点4 re模块基本用法-raw
re模块基本用法-raw
r’sanle’ 中的r代表的是raw(原始字符串)
·原始字符串与正常字符串的区别是原始字符串不会将\字符解释成一个转义字符
·正则表达式使用原始字符很常见且有用
示例
[root@sanchuang-linux ~]# echo -e 'sbc\ndef' # 注:shell里-e让它转义
sbc
def
>>> a="abc\ndef"
>>> print(a) # 注:Python里默认被转义
abc
def
>>> print(r"abc\ndef") # 注:接r 不被转义
abc\ndef
>>> result = re.search("\tsanle", "hello\tsanle") # 注:先转义tab sanle 再传入real解释器
>>> result # 注:匹配上了
<_sre.SRE_Match object; span=(5, 11), match='\tsanle'>
>>> result = re.search("\\tsanle", "hello\\tsanle") # 注:没有匹配到
>>> result # 注:第一层转义\tsanle 再传入re解释器
>>> result = re.search(r"\\tsanle", "hello\\tsanle") # 注:以原始字符串的形式去传给re解释器
>>> result # 注:接r 第一层不转义 \\tsanle 再传入re解释器
<_sre.SRE_Match object; span=(5, 12), match='\\tsanle'> # 注:re解释器 再去转义
>>> print(r"\\t")
\\t
>>> result = re.search("\\tsanle", "hello\\\tsanle")
>>> result
<_sre.SRE_Match object; span=(6, 12), match='\tsanle'>
#注:反斜杠\有特殊含义;没有特殊含义用2个\\,仅仅表示字符“\……”
>>> result = re.search("\\tsanle", "hello\\tsanle") # 注:先转义成\tsanle 再正则传入
>>> print("hello\\\tsanle") # 注:\转义成“\”本身,\t转义成tab键盘
hello\ sanle
>>> re.search("\\\tsanle", "hello\\\tsanle") # 注:进行2次转换 1.\\\t-->\t 2.正则表达式处理
<_sre.SRE_Match object; span=(6, 12), match='\tsanle'>
#注:不转义时 \\t \\t 第一层转换 本身先转换(先转换,再交给正则表达式去处理)
#注:给到real解释器时 交给\t
>>> re.search("\\\\tsanle", "hello\\\\tsanle")
<_sre.SRE_Match object; span=(6, 13), match='\\tsanle'> # 注:匹配到\t 不会再转换成tab
#注:接r 第一层不转义,以原始字符串的形式 交给正则表达式去处理
>>> re.search(r"\\\\tsanle", "hello\\\\tsanle")
<_sre.SRE_Match object; span=(5, 13), match='\\\\tsanle'>
知识点5 re模块基本用法-match对象
match.group(default=0):返回匹配的字符串。
·group是由于正则表达式可以分拆为多个只调出匹配子集的子组。
·0是默认参数,表示匹配的整个串,n 表示第n个分组
match.start()
·start方法提供了原始字符串中匹配开始的索引
match.end()
·end方法提供了原始字符串中匹配开始的索引
match.groups()
·groups返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
#注:搜索出来的东西就是match对象
示例1
>>> msg = "It's raining cats and dogs"
>>> match = re.search(r"cats",msg)
>>> match
<_sre.SRE_Match object; span=(13, 17), match='cats'> # 注:返回match对象
>>> dir(match) # 注:查看match属性
………………'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']
示例2
import re # 直接导入 内置模块
#match对象
msg = "It's raining cats and dogs, cats1 cats2"
match = re.search(r"cats",msg) # 注:获取 返回的对象
#注:访问属性 捞取返回对象的内容
print(match.group()) # 注:获取匹配的项(匹配的内容)
print(match.start()) # 注:获取内容开始下标索引
print(match.end()) # 注:获取内容结束下标
cats
13
17
示例3
>>> match = re.search(r"cats",msg)
>>> match.groups() # 注:没获取到
()
>>> match = re.search(r"(cats)",msg) # 注:匹配时加括号 获取组
>>> match.groups() # 注:以元组的形式存储
('cats',) # 注:以元组的形式存储(区分集合和元组 一个元素+逗号)
知识点6 re模块基本用法-findall finditer
re模块基本用法-findall
findall和finditer:找到多个匹配
re.findall
·查找并返回匹配的字符串,返回一个列表
re模块基本用法-finditer
findall和finditer:找到多个匹配
re.finditer
·查找并返回匹配的字符串,返回一个迭代器
示例
import re
msg = "It's raining cats and dogs, cats1 cats2"
result = re.findall("cats",msg) # 前面是表达式,后面是要匹配的项
print(result) # 注:findall 找全部
result2 = re.finditer("cats",msg)
print(result2) # 注:返回的是一个对象object iterator 生成器 不能直接输出获取,使用的时候去获取
for i in result2: # 注:放在迭代器里面,用for循环去获取 (列表元组字符串也是迭代器)
print(i) # 注:生成3个对象 依次做出
print(i.group())
result2 = re.finditer("cats",msg)
print(list(result2)) # 注:或者转换成列表 去获取 (前面取出来了后面会获取不到)
['cats', 'cats', 'cats']
<callable_iterator object at 0x0000019031431160>
<re.Match object; span=(13, 17), match='cats'>
cats
<re.Match object; span=(28, 32), match='cats'>
cats
<re.Match object; span=(34, 38), match='cats'>
cats
[<re.Match object; span=(13, 17), match='cats'>, <re.Match object; span=(28, 32), match='cats'>, <re.Match object; span=(34, 38), match='cats'>]
知识点7 re模块基本用法-sub
re模块基本用法-sub
re.sub(‘匹配正则’,‘替换内容’,‘string’)
·将string中匹配的内容替换为新内容 # 注:替换全部
示例1
import re
msg = "I am learning python python2 python3"
print(re.sub("python","PYTHON",msg)) # 注:第1个匹配正则,第2个替换的内容
#注:将小写的python替换成大写的
#I am learning PYTHON PYTHON2 PYTHON3
示例2:字符串替换
>>> a="abc123"
>>> a.replace('123','def') # 注:能不使用正则就不使用正则
'abcdef'
知识点8 re模块基本用法-compile
re模块基本用法-compile # 注:复杂的正则可以复用,不用重复写正则表达式
编译正则:re.compile(‘匹配正则’)
reg = re.compile(r’l+’)
result = reg.search(Zen)
print(result, type(result))
编译正则的特点:
·复杂的正则可复用。
·使用编译正则更方便,省略了参数。
·re模块缓存它即席编译的正则表达式,因此在大多数情况下,使用compile并没有很大的性能优势
#注:因为相同的正则表达式第一次编译后会有缓存,第二次编译时会找缓存。2种方式性能一样
#注:不同的对象 或者 复杂的正则 建议先编译
#注:linux里面用grep去支持正则,Python里用re模块
示例
import re
#compile
msg = "I am learning python python2 python3"
msg2 = "I am learning English"
msg3 = "hello world"
print(re.findall("python",msg))
reg = re.compile("python") # 注:返回正则表达式变量 赋给reg变量
print(reg.findall(msg)) # 注:用这种方法 是把它的正则表达式 编译成一个对象
print(reg.findall(msg2)) # 注:编译成对象,再使用对象的属性去获取
print(reg.findall(msg3)) # 注:对于复杂的正则表达式,一般先把它编译成一个对象
print(re.findall("python",msg2)) # 注:避免这类写法重复
[‘python’, ‘python’, ‘python’]
[‘python’, ‘python’, ‘python’]
[]
[]
[]
示例:类似于1个切片对象
#注:类似于1个切片对象
#注:后面直接生成 使用切片对象
>>> a="abc123"
>>> a.replace('123','def')
'abcdef'
>>> lst = ["a","b","c"]
>>> lst2 = [1,2,3]
>>> slc = slice(1,2)
>>> lst[slc]
['b']
>>> lst2[slc]
[2]
>>> lst[1:2]
['b']
知识点9.1 基本正则匹配-区间
基本正则匹配-区间
最简单的正则表达式是那些仅包含简单的字母数字字符的表达式,复杂的正则可以实现强大的匹配
区间:[]
·正则匹配区分大小写
·匹配所有字母:[a-zA-Z]
·匹配所有字母及-:[a-zA-Z-] # 注:- 需要转义一样 因为 - 在里面表示范围,要变为原始含义
#注:使用ascii码的范围来匹配
示例:区间匹配
#正则表达式
import re
#注:python和linux 匹配正则语法规则都是一样的,因为他们的引擎是一样的
#区间
ret = re.findall("Python","Python 3 python")
print(ret) # 注:匹配大Python
#结果为['Python']
#注:在区间里面随机匹配一个
ret = re.findall("[Ppfp]ython","Python 3 python fython Fython")
print(ret) # 注:相当于在字符串里面找它的子串
#结果为['Python', 'python', 'fython']
ret = re.findall("[a-z]","abcABC123") # 注:区间里面匹配一个字符
#结果为['a', 'b', 'c']
print(ret)
ret = re.findall("[a-zA-Z/-]","abcABC123-") # 注:匹配大小写和-
print(ret) # 注:默认情况下匹配1个
#结果为['a', 'b', 'c', 'A', 'B', 'C', '-']
知识点9.2 基本正则匹配-或匹配
基本正则匹配-或匹配
匹配a或b:a|b
·匹配cat或dog
#注:区间里面本身就有或的含义
#注:区间只能一个匹配,匹配几个字符 用|或运算符 去做
示例
#匹配或
import re
msg = "It's raininf cats and dogs"
ret = re.search("cats|dogs",msg) # 注:search只会返回一个
print(ret) # 注:只会匹配cats
#结果为 <re.Match object; span=(13, 17), match='cats'>
ret = re.findall("cats|dogs",msg) # 注:findall 都返回
print(ret)
#结果为 ['cats', 'dogs']
知识点9.3 基本正则匹配-取反
基本正则匹配-取反
取反:[^abc]
·匹配a+非小写字母
示例
#区间取反
import re
ret = re.search("a[a-z]","1ab3cb3a1a#!aB") # 注:使用search 只返回第一个匹配的
print(ret)
#结果为 <re.Match object; span=(1, 3), match='ab'>
ret = re.search("a[^a-z]","1ab3cb3a1a#!aB") # 注:取反,search只返回第1个匹配的
print(ret)
#结果为 <re.Match object; span=(7, 9), match='a1'>
ret = re.findall("a[^a-z]","1ab3cb3a1a#!aB") # 注:取反,findall 返回所有子串
print(ret)
#结果为 ['a1', 'a#', 'aB']
ret = re.findall("a[^a-z][^a-z]","1ab3cb3a1a#!aB")
print(ret)
#结果为 ['a#!']
#注:区间根据ASCII码来的
#注:表示字母[A-z]
ret = re.findall("[0-Z]","1ab3cb3a1a#!aB") # 注:不包含小写
print(ret)
#结果为 ['1', '3', '3', '1', 'B']
ret = re.findall("[0-z]","1ab3cb3a1a#!aB") # 注:大小写数字都有
print(ret)
#结果为 ['1', 'a', 'b', '3', 'c', 'b', '3', 'a', '1', 'a', 'a', 'B']
#[0-z] --> [0-z] ascii码的区间范围
ret = re.findall("[0-z]","1ab3cb3a1a#>=?!aB")
print(ret)
#结果为 ['1', 'a', 'b', '3', 'c', 'b', '3', 'a', '1', 'a', '>', '=', '?', 'a', 'B']
ret = re.findall("[^0-9A-Za-z]","1ab3cb3a1a#>=?!aB") # 注:取出所有的特殊字符
print(ret)
#结果为 ['#', '>', '=', '?', '!']
知识点9.4 基本正则匹配-任意字符(占位符)
基本正则匹配-任意字符(占位符)
任意字符:“.”占位符
·匹配任何(除\n外)的单个字符,它仅仅只以出现在方括号字符组以外
#注:匹配出换行符之外的任意单个字符,但是必须要有一个字符
示例
#. 占位符,表示任意一个字符(除\n之外)
import re
ret = re.findall("p.thon","Python pYthon python pthon p-thon")
print(ret)
#结果为 ['pYthon', 'python', 'p-thon']
ret = re.findall("p.thon","Python pYthon python pthon p\nthon") # 注:不匹配\n换行符
print(ret)
#结果为 ['pYthon', 'python']
ret = re.findall("p.thon","Python pYthon python pthon p\tthon")
print(ret) # 注:\t也匹配到了
#结果为 ['pYthon', 'python', 'p\tthon']
知识点9.5 基本正则匹配-快捷方式
基本正则匹配-快捷方式
·快捷方式
#注:\B 不作为词边界的
#注:快捷方式基本成对存在
#注:有特殊字符的属于字符的边界
#注:r"\bworld" world前面必须是词边界
#注:123world world123 123不是词边界(相当于world123相当于1个单词)
#r"\bworld\b" 匹配一个world前后都是词边界
#r"\Bworld\B" 匹配一个world前后都不是词边界
示例1:快捷方式 \b词边界 单词边界 ; \B
#注:数字、字母、下划线 不算做边界 (算作单词)
#快捷方式
import re
ret = re.findall(r"\bworld\b","hello world 123world =world ##world##")
#注:需要接r 不给\b进行转义 原始字符写入
#注:转义字符\b表示退格
print(ret)
#结果为 ['world', 'world', 'world']
ret = re.finditer(r"\bworld","hello world world123 123world =world ##world##")
print(list(ret)) # 注:/b匹配词边界 world123 123world 没有被匹配到
#结果为 [<re.Match object; span=(6, 11), match='world'>, <re.Match object; span=(12, 17), match='world'>, <re.Match object; span=(31, 36), match='world'>, <re.Match object; span=(39, 44), match='world'>]
ret = re.finditer(r"\bworld\b","hello world _world world123 123world =world ##world##")
print(list(ret))
#输出为 [<re.Match object; span=(6, 11), match='world'>, <re.Match object; span=(38, 43), match='world'>, <re.Match object; span=(46, 51), match='world'>]
#注:输出为world (=)world (##)world(##)
>>> ret = re.finditer(r"\Bworld\B","_world_ 11world22") # 注:\B 不作为词边界的
>>> print(list(ret))
[<_sre.SRE_Match object; span=(1, 6), match='world'>, <_sre.SRE_Match object; span=(10, 15), match='world'>]
示例2:\w 匹配字母数字下划线; \W 匹配任何非单词字符
ret = re.findall(r"\w","python3#") # 注:匹配一个单词字符
print(ret)
#结果为 ['p', 'y', 't', 'h', 'o', 'n', '3']
ret = re.findall(r"\W","python3#") # 注:取反
print(ret)
#结果为 ['#']
基本正则匹配-快捷方式
快捷方式
·匹配字母数字下划线 \w
·匹配非字母数字 \W
知识点9.6 基本正则匹配-开始与结束
基本正则匹配-开始与结束
开始与结束:^, $
·匹配以python开头:^python
·匹配以python结尾:python$
#^放在区间里面表示取反,放在引号 字符串里表示以……开头
示例
#开始与结束:^, $
#·匹配以python开头:^python
#·匹配以python结尾:python$
ret = re.findall("^python","hello python")
print(ret)
#结果为 [] 空
ret = re.findall("^python","python123#")
print(ret) # 注:匹配以 python开头的python
#结果为 ['python']
ret = re.findall("python$","hello python")
print(ret) # 注:匹配以 python结尾的python
#结果为 ['python']
ret = re.findall("^python$","hello python")
print(ret) # 注:匹配以 python开头 和 结尾的python
#结果为 [] 空
#^放在区间里面表示取反,放在引号 字符串里表示以……开头
知识点10 正则重复-通配符
正则重复-通配符
通配符:?,*,+
符号 功能
? 匹配指定的字符(组)出现0次或1次
-
匹配指定的字符(组)出现1次以上
-
匹配指定的字符(组)出现任意多次
知识点10.1 正则重复-通配符
正则重复-通配符
通配符:“?”
·匹配指定的字符(组)出现0次或1次
示例:?匹配指定的字符(组)出现0次或1次
#注:-w表示字母数字下划线
#正则重复-通配符
#通配符:?,*,+
import re
ret = re.findall("\w?","python#!3")
print(ret)
#结果为 ['p', 'y', 't', 'h', 'o', 'n', '', '', '3', '']
#注:# ! 匹配0次 为空,结尾会多匹配一下为空
知识点10.2 正则重复-通配符
正则重复-通配符
通配符:“*”
·匹配指定的字符(组)出现任意多次
示例
#* 0次到任意次
ret = re.findall("\w*","python3#")
print(ret) # 注:数字字母下划线 匹配0次或任意次 python3 ;#不是\w 匹配0次
#结果为 ['python3', '', '']
知识点10.3 正则重复-通配符
正则重复-通配符
通配符:“+”
·匹配指定的字符(组)出现1次以上
示例
#+ 1次以上
ret = re.findall("\w+","python3#")
print(ret) # 注:python3 匹配了任意次 显示;#匹配0次 不显示
#结果为 ['python3']
知识点10.4 正则重复-通配符
正则重复-通配符
通配符:“{n, m}”
·匹配指定的字符(组)出现1次以上
示例
#{n,m} 指定匹配n到m次
ret = re.findall("\w{1,3}","python3#")
print(ret)
#结果为 ['pyt', 'hon', '3']
知识点11 基本正则匹配-贪婪与非贪婪模式
基本正则匹配-贪婪与非贪婪模式
贪婪模式与非贪婪模式
·贪婪模式(.): 匹配尽可能多的字符-默认模式 # 注:匹配前一个字符0次或任意次
·非贪婪模式(.?): 正则 \d*?
·匹配出
示例
#贪婪模式和非贪婪模式
msg = "<div>test</div>bb<div>test2</div>"
ret = re.findall("<div>.*</div>",msg) # 注:匹配开始标签和闭合标签
print(ret) # 注:贪婪模式,匹配尽可能多的字符
#结果为 ['<div>test</div>bb<div>test2</div>']
ret = re.findall("<div>.*?</div>",msg) # 注:匹配尽可能短的字符
print(ret) # 注:非贪婪模式,满足条件就返回,不会再去匹配其他的
#结果为 ['<div>test</div>', '<div>test2</div>']
ret = re.findall("\w*?","python3#") # 注:非贪婪模式
print(ret) # 注:尽可能短的匹配
#结果为 ['', 'p', '', 'y', '', 't', '', 'h', '', 'o', '', 'n', '', '3', '', '']
ret = re.findall("\w{1,3}?","python3#") # 注:非贪婪模式
print(ret) # 注:默认情况是贪婪模式
#结果为 ['p', 'y', 't', 'h', 'o', 'n', '3']
示例:匹配正整数
>>> import re
>>> re.findall(r"^\+?[1-9]\d*$","123") # 注:\+ 表示+号 不转义;以+(0次或1次)开头
['123'] # 注:以+(0次或1次)开头;以数字结尾
>>> re.findall(r"^\+?[1-9]\d*$","+123")
['+123']
>>> re.findall(r"^\+?[1-9]\d*$","+0123")
[]
>>> re.findall(r"^\+?[1-9]\d*$","abc123")
[]