一、正则表达式的概念
正则表达式(Regular Expression)是一种用来描述文本模式的工具,通常用来匹配、搜索或替换文本。它由一些元字符(也称为转义字符或控制字符)和普通字符(例如字母、数字、标点符号等)组成,并使用一些特定的语法规则,可以用来匹配字符串中的某些模式。正则表达式可以用于多种编程语言和应用程序中,例如Java、JavaScript、Python、PHP等。
在Python中,我们可以使用re模块来实现正则表达式的相关操作。该模块提供了许多函数和方法,包括编译正则表达式、匹配字符串、查找子串、分割字符串等功能。
二、正则表达式中常见的功能字符
三、正则表达式中的特殊字符
1.范围符号[ ]和量词
1.1 范围符号[XXX]的用法
[XXX]的用法如下
1.2匹配汉字
print('\u4e00\u4e01\u4e88\u9fa5') #>>一丁予龥
1.3量词的用法
'.+' 匹配任意长度不为0且不含'\n'的字符串。'+'表示左边的'.'代表的任意 字符出现1次或更多次。不要求出现的字符都必须一样。
1.4示例
四、使用正则表达式
使用前,要先:
import re
1.re.match函数
import re
def match(pattern,string):
x = re.match(pattern,string)
if x != None:
print(x.group()) #x.group是匹配上的字符串
else:
print("None")
match("a c","a cdkgh") #>>a c
match("abc","kabc") #>>None 虽然有abc,但不是在起始位置
match("a\tb*c","a\tbbcde") #>>a bbc b出现0次或任意多次,然后跟c
match("ab*c","ac") #>>ac
match("a\d+c","ac") #>>None b出现1次或更多次,然后跟c
match("a\d{2}c","a34c") #>>a34c
match("a\d{2,}c","a3474884c") #>>a3474884c
match(".{2}bc","cbcd") #>>None bc前面要有2个字符
match(".{2}bc","bcbcdbc") #>>bcbc
match("ab.*","ab") #>>ab b后面可以没字符或任意字符
match("ab.*","abcd") #>>abcd
match("\d?b.*","1bcd") #>>1bcd 数字应出现0次或1次
match("\d?b.*","bbcd") #>>bbcd
match("a?bc.*","abbbcd") #>>None b太多了
match("a.b.*","abcd") #>>None a和b之间必须要有一个字符
match("a.b.*","aeb") #>>aeb
match("a.?b.*","aebcdf") #>>aebcdf
#a和b之间没字符或有任意一个字符均可
match("a.+b.*","aegsfb") #>>aegsfb
match("a.+b.*","abc") #>>None
match("a高.+k","a高大kcd") #>>a高大b
2.re.search函数
import re
def search(pattern,string):
x = re.search(pattern,string)
if x != None:
print(x.group(),x.span()) #输出子串及起止位置
else:
print("None")
search("a.+bc*","dbaegsfbcef") #>>aegsfbc (2, 9)
search("a.+bc*","bcdbaegsfbccc") #>>aegsfbccc (4, 13)
search("a.?bc*d","dabccdc") #>>abccd (1, 6)
search("aa","baaaa") #>>aa (1, 3)
search("\([1-9]+\)","ab123(0456)(789)45ab") #>>(789) (11, 16)
search("[1-9]\d+","ab01203d45") #>>1203 (3, 7)
3.re.findall函数
import re
print(re.findall('\d+',"this is 334 what me 774gw")) #>>['334','774']
print(re.findall('[a-zA-Z]+',"A dog has 4 legs.这是true"))
#>>['A', 'dog', 'has', 'legs', 'true']
print(re.findall('\d+',"this is good.")) #>>[]
print(re.findall("aaa","baaaa")) #>>['aaa']
4.re.finditer函数
import re
s = '233[32]88ab<433>(21)'
m = '\[\d+\]|<\d+>' # | 表示 '或'
for x in re.finditer(m,s): #x是匹配对象
print(x.group(),x.span())
i = 0
for y in re.finditer(m,"aaaaa"):
i += 1 #不会被执行
五、边界符号
print("\A\Z") #>>\A\Z
import re
def search(pattern,string):
x = re.search(pattern,string)
if x != None:
print(x.group())
else:
print("None")
m = "\Ahow are"
search(m,"ahow are you") #>>None
search(m,"how are you") #>>how are
m = "are you\Z"
search(m,"how are you?") #>>None
search(m,"how are you") #>>are you
search("a.+bc*","dbaegsfbcef") #>>aegsfbc
search("a.+bc*\Z","dbaegsfbcef") #>>None
search("a.+bc*\Z","dbaegsfbccc") #>>aegsfbccc
Python字符串 '\B' 是两个字符
print("\\b") #>>\b
pt = "ka\\b.*"
search(pt,"ka") #>>ka
search(pt,"kax") #>>None
search(pt,"ka?d") #>>ka?d
pt = ".*\\bka\\b"
search(pt,"ka") #>>ka
search(pt,"ska?") #>>None
search(pt,"b?ka?") #>>b?ka
m = r"\bA.*N\b T" #等价于 m = "\\bA.*N\\b T"
search(m,"Ass$NC TK") #>>None
search(m,"this Ass$N TK") #>>Ass$N T
m = "\BA.*N\B\w T"
search(m,"this Ass$N TK") #>>None
search(m,"thisAss$NM TK") #>>Ass$NM T
search(m,"Ass$NM TK") #>>None
search(m,"xAss$NM TK") #>>Ass$NM T
pt = "\\b高兴"
search(pt,"我高兴") #None
search(pt,"我 高兴") #高兴
六、匹配选项
![](https://i-blog.csdnimg.cn/blog_migrate/71d5f8c6523921fcee5d411cc2c2ad23.png)
正则表达式匹配选项:
import re
def search(pattern,string ,flags = 0):
#flags参数如果省略不写,其值就是 0
x = re.search(pattern,string,flags)
if x != None:
print(x.group())
else:
print("None")
search("a.+b.*","acBc") #>>None
search("a.+b.*","acBc",re.I) #>>acBc
m = "^h[a-z]w are"
g = re.findall(m,"how are you\nhew are me")
print(g) #>>['how are']
g = re.findall(m,"how are you\nhew ARE me",re.M|re.I)
#多行匹配模式且不分大小写
print(g) #>>['how are', 'hew ARE']
m = "are you$"
search(m,"how are you\nThis") #>>None
search(m,"how are you\nThis",re.M) #>>are you
search("a.+b","a\ncdb") #>>None
search("a.+b","a\ncdbe",re.S)
七、分组(...)
import re
x = re.search('[a-z]+(\d+)[a-z]+',"ab 123d hello553world47")
print(x.group(1)) #>>553
m = "(((ab*)c)d)e"
r = re.match(m,"abcdefg")
print(r.group(0)) #>>abcde group(0)等价于group()
print(r.group(1)) #>>abcd
print(r.group(2)) #>>abc
print(r.group(3)) #>>ab
print(r.groups()) #>>('abcd', 'abc', 'ab')
import re
m = "(ab*)(c(d))e"
r = re.match(m,"abcdefg")
print(r.groups()) #>>('ab', 'cd', 'd')
print(r.group(0)) #>>abcde
print(r.group(1)) #>>ab
print(r.group(2)) #>>cd
print(r.group(3)) #>>d
import re
m = r'(((ab*)c)d)e\3' #r表示字符串里的'\'不再转义
#要求 ab*cde后面跟着3号分组在本次匹配中匹配上的子串
r = re.match(m,"abbbcdeabbbkfg") # 红色部分少一个b则不能匹配
print(r.group(3)) # abbb
print(r.group()) # abbbcdeabbb
pt = 'a(.)\\1*b' #或 pt = r'a(.)\1*b'
print(re.search(pt,'kacccccb').group()) #>>acccccb
print(re.search(pt,'kaxxxxb').group()) #>>axxxxb
print(re.search(pt,'kaxb').group()) #>>axb
x = re.search(pt,'kaxyb')
if x != None:
print(x.group()) #不会执行
分组作为一个整体,后面可以跟量词
import re
m = "(((ab*)+c)d)e"
r = re.match(m,"ababcdefg")
print(r.groups()) #>>('ababcd', 'ababc', 'ab')
r = re.match(m,"abacdefg")
print(r.groups()) #>>('abacd', 'abac', 'a')
1.re.findall和分组
import re
m = '[a-z]+(\d+)[a-z]+'
x = re.findall(m,"13 bc12de ab11 cd320ef")
print(x) #>>['12', '320']
2.findall和分组
import re
m = '(\w+) (\w+)'
r = re.match(m,"hello world")
print(r.groups()) #>>('hello', 'world')
print(r.group(1)) #>>hello
print(r.group(2)) #>>world
r = re.findall(m,"hello world, this is very good")
#找出由所有能匹配的子串的 groups() 构成的元组,互相不重叠
print(r) #>>[('hello', 'world'), ('this', 'is'), ('very', 'good')]
3.re.sub和分组
import re
s = 'abc.xyz'
print(re.sub(r'(.*)\.(.*)', r'\2.\1', s)) #>>xyz.abc
4.''|''的用法
import re
pt = "\d+\.\d+|\d+"
print(re.findall(pt,"12.34 this is 125"))
#>>['12.34', '125']
pt = "aa|aab"
print(re.findall(pt,"aabcdeaa12aab"))
import re
m ="(((ab*)+c|12)d)e"
print(re.findall(m,'ababcdefgKK12deK'))
#>>[('ababcd', 'ababc', 'ab'), ('12d', '12', '')]
for x in re.finditer(m,'ababcdefgKK12deK'):
print(x.groups())
#>>('ababcd', 'ababc', 'ab')
#>>('12d', '12', None)
m = '\[(\d+)\]|<(\d+)>'
for x in re.finditer(m,'233[32]88ab<433>'):
print(x.group(),x.groups())
八、贪婪模式和懒惰模式
1.量词的贪婪模式
import re
print(re.match("ab*", "abbbbk").group()) #>>abbbb
print(re.findall("<h3>(.*)</h3>",
"<h3>abd</h3><h3>bcd</h3>"))
print(re.findall('\(.+\)',
"A dog has(have a).这(哈哈)true()me"))
2.量词的非贪婪(懒惰)模式
import re
m = "a.*?b"
for k in re.finditer(m,"aabab"):
print(k.group(),end=" ") #>>aab ab
m = "<h3>.*?</h3>"
a = re.match(m,"<h3>abd</h3><h3>bcd</h3>")
print(a.group()) #>><h3>abd</h3>
m = "<h3>.*?[M|K]</h3>"
a = re.match(m,"<h3>abd</h3><h3>bcK</h3>")
print(a.group()) #>><h3>abd</h3><h3>bcK</h3>
import re
print(re.findall('\d+?',"this is 334 what me 774gw"))
#>>['3', '3', '4', '7', '7', '4']
print(re.findall('[a-zA-Z]+?',"A dog has 4 legs.这是true"))
#>>['A', 'd', 'o', 'g', 'h', 'a', 's', 'l', 'e', 'g', 's', 't',
'r', 'u', 'e']
print(re.findall('\(.*?\)',"A dog has(have).这(哈哈)true()me"))
#>>['(have)', '(哈哈)', '()']
九、匹配对象
1.''匹配对象''(匹配成功时的返回结果)的属性
2.''匹配对象''的函数
m = re.match(r'(\w+) (\w+)(.)', 'hello world!ss')
print( m.string) #>>hello world!ss
print(m.lastindex) #>>3
print(m.group(0,1,2,3))#>>('hello world!', 'hello', 'world', '!')
print(m.groups()) #>>('hello', 'world', '!')
print(m.start(2)) #>>6
print(m.end(2)) #>>11
print(m.span(2)) #>>(6, 11)
十、应用实例
import re
f = open("c:/tmp/三国演义utf8.txt","r",encoding="utf-8")
txt = f.read()
f.close()
pt = "(孔明.{0,2}曰:“[^”]*(曹操|曹贼|操贼|曹阿瞒|操).*?”)"
a = re.findall(pt,txt)
print(len(a)) #>>58
②抽取ip地址、邮箱、网址
import re
ipadr = r"\b((25[0-5]|2[0-4]\d|((1\d{2})|([1-
9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\b"
mailbox = r"\b[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-
]+)+\b"
url = r'http://[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-
a-zA-Z0-9]{0,62})+(/[-a-zA-Z0-9]+)*\b'
s = "My ip is 225.124.3.4", this is
https://www.python.org, http://www.sohu.com
my mailbox is 1252806160@qq.com. ok?"
m = re.search(ipadr,s)
if m != None:
print(m.group()) #>>225.124.3.4
m = re.search(mailbox,s)
if m != None:
print(m.group()) #>>1252806160@qq.com
for x in re.finditer(url,s):
print(x.group())
#>>
https://www.python.org
http://www.sohu.com
总结
以上便是关于python正则表达式的基本内容,虽然正则表达式很强大,但也有一些缺点,比如代码可读性差、易出错等。因此,在实际开发中需要根据具体情况选择合适的工具。
这篇文章只能算是个学习笔记。我本身也是个初学者,有错漏的地方也是难免的,所以最可靠的,还是Python自带的帮助。以及网络上寻找的一些资料。
此文章参考了MOOC北京大学郭炜老师的《实用python程序设计》
whitefish2023.8.27