1、正则表达式的定义
- 又叫做规则表达式,英语:Regular Expression,在代码中常简写为regex、regexp或RE
- 正则表达式描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。本质是由一系列特殊符号和字符组成的字串。
-
构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
-
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
2、产生原因和特点
- 文本处理已经成为计算机常见工作之一
- 对文本内容的搜索,定位,提取是逻辑比较复杂的工作
- 为了快速方便的解决上述问题,产生了正则表达式。
- 优点:方便进行检索修改文本的操作,支持编程语言众多,使用灵活多样。
3、Python re 模块
- re.findall(pattern,string)
- 功能:使用正则表达式匹配字符串,如果正则表达式有分组则只显示子组内容。
- 参数:pattern 正则表达式字符串 string 目标字符串
- 返回值: 返回一个列表 匹配到的内容
import re
s = "my email is Levi@126.com or lvze@tedu.cn"
print(re.findall("\w+@\w+\.\w{2,3}",s))
运行结果:['Levi@126.com', 'lvze@tedu.cn']
- regex = re.compile(pattern,flags=0)
- 功能:生成正则表达式对象
- 参数:pattern 正则表达式
- flags 功能标志位,丰富正则的匹配功能
- 返回值:正则表达式对象
import re
regex = re.compile("abc")
print(dir(regex))
运行结果:['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'findall', 'finditer', 'flags', 'fullmatch', 'groupindex', 'groups', 'match', 'pattern', 'scanner', 'search', 'split', 'sub', 'subn']
- list = regex.findall(string,pos=0,endpox=999)
- 功能:根据正则表达式匹配目标字符串
- 参数:string 目标字符串
- pos 标明从目标字符串的哪个位置开始匹配
- endpos 标明匹配到目标字符串的哪里
- 返回:返回一个列表,内部为匹配到的内容
import re
#re调用findall
s = "abcdfghi"
l = re.findall(r"ab",s)
print(l)
#利用regex对象来调用findall
regex = re.compile(r"abcd")
l = regex.findall(s)
print(l)
运行结果:
['ab']
['abcd']
- re.finditer(pattern,string,flags)
- 功能:使用正则表达式匹配目标字符串
- 参数:pattern 正则
- string 目标字符串
- 返回值:将匹配内容生成迭代器
import re
#替换目标字符串
s = "2020年是个多事之秋,125新冠病毒"
it = re.finditer(r"\d+",s)
for i in it:
print(i.group())
运行结果:
2020
125
- re.fullmatch(pattern,string,flags)
- 功能:完全匹配目标字符串
- 参数:pattern 正则表达式
- string 目标字符串
- 返回值:匹配到的内容(match object)
import re
try:
obj = re.fullmatch(r'\w+','abcde#f123')
print(obj.group())
except AttributeError as e:
print(e)
- re.match(pattern,string,flags)
- 功能:匹配目标字符串开头
- 参数:pattern 正则
- string 目标字符串
- 返回值:匹配到的内容 (match object)
import re
#匹配字符串开始位置
obj = re.match("foo","foo,food on the table")
print(obj.group())
运行结果:foo
- re.search(pattern,string,flags)
- 功能:匹配目标字符串,只能匹配第一处
- 参数:pattern 正则表达式
- string 目标字符串
- 返回值:匹配到的内容(match object)
- 注意:生成match对象如果失败返回None,则无法调用match对象属性,此时会产生异常。
import re
#匹配字符串第一次出现位置
obj = re.search("foo","Foo,food on the table")
print(obj.group())
运行结果:foo
- re.split(pattern,string,flags=0)
- 功能:通过正则表达式分割字符串
- 参数:pattern 正则表达式
- string 目标字符串
- 返回值:分割后字符串列表
import re
#分割字符串
s = "he is good boy"
l = re.split(r"\s+",s)
print(l)
运行结果:
['he', 'is', 'good', 'boy']
- re.sub(pattern,replaceStr,string,max,flags)
- 功能:替换正则表达式匹配到的内容
- 参数:pattern 正则
- replaceStr 要替换的内容
- string 目标字符串
- max 最多替换几处(如果超过,按最多)
- 返回值:返回替换后的字符串
import re
#替换目标字符串
s = re.sub(r"\s+","##","hello world nihao")
print(s)
运行结果:hello##world##niha
- re.subn(pattern,replaceStr,string,max,flags)
- 功能:替换正则表达式匹配到的内容
- 参数:pattern 正则
- replaceStr 要替换的内容
- string 目标字符串
- max 最多替换几处
- 返回值:返回替换后的字符串和替换几处。
import re
#替换目标字符串
s = re.subn(r"\s+","##","hello world nihao")
print(s)
运行结果:('hello##world##nihao', 2)
-
compile生成对象的属性
-
pattern 正则对象对应的正则表达式
-
flags 获取标志位值
-
groupindex 获取捕获组形成的字典(组名为键,第几组为值)
-
groups 多少子组
4、正则表达式字符
- 普通字符 包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。eg:a,b,c,
- 匹配规则:匹配字符本身
import re
s = "abc ddfal dafkjlfasldfjabc"
print(re.findall("abc",s))
运行结果:['abc', 'abc']
import re
s = "大家好,我是中国人民,我爱中国"
print(re.findall("中国",s))
运行结果:['中国', '中国']
- 或 |
- 匹配规则:匹配 | 两边任意一个正则表达式
- 注意:两边内容不能重合的。如果重合只能匹配一个,不要加没用空格。
import re
s = "asdfasdfadsfasdfasdfasdfbadasdf"
print(re.findall("as|fa",s)) #注意不能有空格,空格也属于表达式字符。
运行结果:['as', 'fa', 'fa', 'fa', 'fa', 'fa', 'as']
- 匹配单一字符 · (点)
- 匹配规则:匹配除了\n 任意一个字符
- eg: f.o >> fao,foo
import re
re.findall("f.o","fao is not foo")
运行结果:['fao', 'foo']
- 匹配开始位置 ^
- 匹配规则:匹配一个字符串的开始位置
import re
print(re.findall("^hello","hello world, hello, everone"))
运行结果:['hello']
- 匹配结尾位置 $
- 匹配规则:匹配一个字符串的结束位置
import re
print(re.findall("e$","hello world, hello, everone"))
运行结果:['e']
- 匹配重复 *
- 匹配规则:匹配前面的正则表达式重复0次或者多次
- fo* ---> f(重复0次) foo fooo foooooo
import re
print(re.findall("fo*","fofoodsffoooosdfldk"))
运行结果:['fo', 'foo', 'f', 'foooo', 'f']
- 匹配重复 +
- 匹配规则:匹配前面的正则表达式1次或多次
- eg: ab+ --> ab abbb
import re
print(re.findall("fo+","fofoodsffoooosdfldk"))
运行结果:['fo', 'foo', 'foooo']
- 匹配重复 ?
- 匹配规则:匹配前面出现的元字符 0 次或 1次
import re
print(re.findall("fo?","fofoodsffoooosdfldk"))
运行结果:['fo', 'fo', 'f', 'fo', 'f']
- 匹配重复 {n}
- 匹配规则:匹配前面的正则表达式n次
- eg: ab{3} abbb
import re
print(re.findall("fo{3}","fofoodsffoooosdfldk"))
运行结果:['fooo']
- 匹配重复 {m,n}
- 匹配规则: 匹配前面的正则表达式 m -- n 次
- ab{3,5} --> abbb abbbb abbbb
import re
print(re.findall("fo{1,3}","fofoodsffoooosdfldk"))
运行结果:['fo', 'foo', 'fooo']
- 匹配字符集合 [字符集]
- 匹配规则:匹配括号内任意一个字符
- [abcd] a b c [a-z] [A-Z] [1-9] 匹配所有小写,大写,字符等。
import re
print(re.findall("[a-z]","sdf1321asdf45564"))
运行结果:['s', 'd', 'f', 'a', 's', 'd', 'f']
- 匹配字符集合 [^…]
- 匹配规则:除了字符集中的任意一个字符
- [^abc] -->除了a,b,c字符之外的其他字符。
import re
print(re.findall("[^abc]","sdf1321asdf45564"))
运行结果:['s', 'd', 'f', '1', '3', '2', '1', 's', 'd', 'f', '4', '5', '5', '6', '4']
- 匹配任意(非)数字字符 \d \D
- 匹配规则:\d 匹配任意数字字符 [0-9]
- \D 匹配任意非数字字符 [^0-9]
import re
print(re.findall("1\d{10}","15978883822"))
运行结果:['15978883822']
import re
print(re.findall("\D","The num is 1234"))
运行结果:['The num is ']
- 匹配(非)普通字符 \w \W
- 匹配规则: \w 匹配任意一个普通字符 等价于[_0-9a-zA-Z]
- \W 匹配任意一个非普通字符 [^_0-9a-zA-Z]
import re
print(re.findall("\w+","Today is sunday!%$#%#%$#%"))
运行结果:['Today', 'is', 'sunday']
import re
print(re.findall("\W+","Today is sunday!%$#%#%$#%"))
运行结果:[' ', ' ', '!%$#%#%$#%']
- 匹配(非)空字符 \s \S (空格,\r \t \n \0)
- 匹配规则: \s 匹配任意空字符
- \S 匹配任意非空字符
import re
print(re.findall("\s+","hello world\t\n\0"))
运行结果:[' ', '\t\n']
import re
print(re.findall("\S+","hello world\t\n\0"))
运行结果:['hello', 'world', '\x00']
- 匹配起止位置 \A \Z
- 匹配规则: 匹配字符串的开始后和结束位置 等价与^ $
- 绝对匹配:正则表达式前后加 ^$ 或/A/Z 表示正则表达式需要匹配目标字符串的全部内容
import re
print(re.findall("/Ahello world/Z","hello world,heihei"))
运行结果: []
- 匹配(非)单词边界 \b \B (普通字符和其他字符交接的位置为单词边界)
- 匹配规则: \b 单词边界 (\b python有这个转义,会冲突。) \\b 或 加 r
- \B 非单词边界
import re
print(re.findall(r"\bis\b","This is Tom!"))
运行结果:['is']
- 匹配单个字符: a · \d \D \w \W \s \S [....] [^....]
- 匹配重复性:* + ? {n} {m,n}
- 匹配位置:^ $ \A \Z \b \B
- 其他: | () \
-
转义字符
- 特殊符号需要搜索,可以用\(反斜杠) 来表示。
import re
print(re.findall("ok\\?","Are you ok?"))
运行结果:['ok?']
- r ---- raw 字符串 原生字符串。字符串的内容就是字符串本身。不进行任何转义处理。
5、贪婪与不贪婪
- 贪婪模式:正则表达式的重复默认总是尽可能多的向后匹配内容。 * + ? {m,n}
- 非贪婪模式:尽可能少的匹配内容。 后面加一个问号
import re
r = re.findall(r"ab+","abbbbbbde") #贪婪模式
print(r)
r = re.findall(r"ab+?","abbbbbbde") #非贪婪模式
print(r)
运行结果:
['abbbbbb']
['ab']
6、正则表达式分组
- 可以使用()为一个正则表达式建立子组,子组可以看作正则表达式的一个局部整体。
- 子组的作用:
- 子组作为一个剧本整体可以改变某些元字符的行为,比如重复,或。
- 子组在某些操作中可以单独提取匹配内容。
- 子组使用注意事项
- 一个正则表达式中可以有多个子组,正则表达式依然是通过整体匹配内容。
- 子组由外到内,由左到右为第一,第二,第三。。。。。子组
- eg: ((ab)cd(ef)) abcdef ab ef
- 足足内容不会重叠。
#() 演示,多个字符查找。
import re
r = re.search(r"(ab)+","abababde").group()
print(r)
运行结果:ababab
import re
r = re.search(r".+(\.com|\.cn)","105115@qq.com,789@tedu.cn").group()
print(r)
运行结果:105115@qq.com,789@tedu.cn
#对获取的内容进行提取。
import re
r = re.search(r"(ab)+","abababde").group(1)
print(r)
运行结果:ab
- 捕获组和非捕获组(命名组,非命名组)
- 格式(?P<name>pattern)
- eg:(r"(?P<dog>ab)","abcdefgh")
- 命名作用:很多编程接口可以通过名称获取指定组内容
- 命名组可以被重复调用。 格式:(?P=name)
import re
r = re.search(r"(?P<dog>ab)cd(?P=dog)","abcdab").group()
print(r)
运行结果:abcdab
7、正则表达式设计原则
- 正确性,能够正确的匹配要求内容
- 唯一性,除了需要匹配的内容,尽可能不匹配不需要的内容。
- 全面性,对目标特征考虑全面不遗漏。