概念
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表述式用于搜索、替换和解析字符串。
正则表达式遵循一定的语法规则,使用非常 灵活,功能强大。使用正则表达式编写一些逻辑验证非常方便,例如电子邮件地址格式的验证。
简介
正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。
作用
1.给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)。
2.可以通过正则表达式,从字符串中获取我们想要的特定部分。
3.还可以对目标字符串进行替换操作。
Python正则表达式的使用
Python 语言通过标准库中的 re 模块支持正则表达式。re 模块提供了一些根据正则表达 式进行查找、替换、分隔字符串的函数,这些函数使用一个正则表达式作为第一个参数。re 模块常用的函数如下表所示。
函数 | 描述 |
---|---|
match(pattern,string,flags=0) | 根据 pattern从 string 的头部开始匹配字符串,只返回第 1 次匹配成功的对象;否则,返回 None |
findall(pattern,string,flags=0) | 根据 pattern 在 string 中匹配字符串。如果匹配成功,返回包含匹配结果的列表;否则,返回空列表。当 pattern 中有分组时,返回包含多个元组的列表,每个元组对应 1 个分组。flags 表示规则选项,规则选项用于辅助匹 配。 |
sub(pattern,repl,string,count=0) | 根据指定的正则表达式,替换源字符串中的子串。pattern 是一个正则表达式,repl 是用于替换的字符串,string 是源字符串。如果 count 等于 0,则返回 string 中匹配的所有结果;如果 count 大于 0,则返回前 count 个匹配结果 |
subn(pattern,repl,string,count=0) | 作用和 sub()相同,返回一个二元的元组。第1个元素是替换结果,第 2 个元素是替换的次数 |
search(pattern,string,flags=0) | 根据 pattern 在 string 中匹配字符串,只返回第 1 次匹配成功的对象。如果匹配失败,返回 None |
compile(pattern,flags=0) | 编译正则表达式 pattern,返回1个pattern 的对象 |
split(pattern,string,maxsplit=0) | 根据pattern分隔 string,maxsplit 表示最大的分隔数 |
match方法
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话, match()就返回 None。语法格式如下:
这里是引用
re.match(pattern, string,flags=0]
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
String | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。如下表列出正则表达式修饰符 - 可选标志 |
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 做本地化识别(locale-aware)匹配 |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据 Unicode 字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
如果文本模式只是一个普通的字符串,那么待匹配的字符串和文本模式字符串在完全相等的情况下,match 方法会认为匹配成功。如果匹配成功,则 match 方法返回匹配的对象, 然后可以调用对象中的 group 方法获取匹配成功的字符串,如果文本模式就是一个普通的字 符串,那么 group 方法返回的就是文本模式字符串本身。
import re
s='hello world'
pattern='hello'
r=re.match(pattern,s)
print(r)
print(r.group())
print(r.span())
常用匹配符
符号 | 描述 |
---|---|
. | 匹配任意一个字符(除了\n) |
[ ] | 匹配列表中的字符 |
\w | 匹配数字、字母、下划线 |
\s | 匹配空白字符 |
\S | 匹配非空白字符 |
\d | 匹配数字 |
\D | 匹配非数字字符 |
import re
s='a'
s='k'
s='4'
s='_'
s='\n'
pattern='.'
o=re.match(pattern,s)
print(o)
s='0'
s='3'
s='9'
s='a'
pattern='\d'
o=re.match(pattern,s)
print(o)
s='0'
s='5'
s='9'
s='a'
pattern='\D'
o=re.match(pattern,s)
print(o)
s=' '
s='\n'
s='\t'
s='_'
pattern='\s'
o=re.match(pattern,s)
print(o)
s=' '
s='\n'
s='\t'
s='_'
pattern='\S'
o=re.match(pattern,s)
print(o)
s='z'
s='A'
s='8'
s='_'
s='#'
pattern='\w'
o=re.match(pattern,s)
print(o)
s='z'
# s='A'
s='8'
s='_'
s='#'
s='+'
pattern='\W'
o=re.match(pattern,s)
print(o)
pattern='[2468]'
s='2'
s='3'
s='4'
s='6'
# s='8'
o=re.match(pattern,s)
print(o)
匹配多个字符
如果要匹配电话号码,需要形如“\d\d\d\d\d\d\d\d\d\d\d”这样的正则表达式。其中表现 了 11 次“\d”,表达方式烦琐。而且某些地区的电话号码是 8 位数字,区号也有可能是 3 位或 4 位数字,因此这个正则表达式就不能满足要求了。正则表达式作为一门小型的语言, 还提供了对表达式的一部分进行重复处理的功能。例如,“*”可以对正则表达式的某个部 分重复匹配多次。这种匹配符号称为限定符。下表列出了正则表达式中常用的限定符。
符号 | 描述 | 符号 | 描述 |
---|---|---|---|
* | 匹配零次或多次 | { m } | 重复m次 |
+ | 匹配一次或多次 | {m,n} | 重复m到n次,其中n可以省略,表示m到任意次 |
? | 匹配一次或零次 | { m ,} | 至少m次 |
转义字符
正则表达式里使用“\”作为转义字符,这就可以能造成反斜杠困扰。假如你需要匹配文本中的字符“\”,那么使用编程语言表示的正则表达式里将需要 4个反斜杠“\\”:前面两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python 里的原生字符串很好地解决了这个问题,使用 Python 的 r 前缀。例如匹配一个数字的“\d”可以写成 r“\d”。有了原生字符串, 再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
print('d:\\a\\b\\c')
print('\nabc')
print('\\nabc')
print('\t123')
print('\\t123')
import re
s='\\t123'
# pattern='\\\\t\d*'
pattern=r'\\t\d*'
o=re.match(pattern,s)
print(o)
s='\\\\t123'
# pattern='\\\\\\\\t\d*'
pattern=r'\\\\t\d*'
o=re.match(pattern,s)
print(o)
边界字符
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词的边界 |
import re
#匹配QQ邮箱 5-10位数字
qq='8656707@qq.com'
qq='8656707@qq.com.cn'
qq='8656707@qq.com.126.com'
# pattern='[1-9]\d{4,9}@qq.com'
pattern=r'[1-9]\d{4,9}@qq.com$'
o=re.match(pattern,qq)
print(o)
# s='hello world'
s='hello python'
s='hepython'
pattern=r'^hello.*'
o=re.match(pattern,s)
print(o)
pattern=r'.*\bab'
s='12345 abc'
o=re.match(pattern,s)
print(o)
pattern=r'.*ab\b'
s='12345 abc'
s='12345 ab'
o=re.match(pattern,s)
print(o)
pattern=r'.*ab\B'
s='12345 abc'
s='12345 ab'
o=re.match(pattern,s)
print(o)
search方法
search 在一个字符串中搜索满足文本模式的字符串。语法格式如下:
这里是引用
re.search(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 如下表列出正则表达式修饰符 -可选标志 |
match 与 search 的区别 :
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None;而 re.search 匹配整个字符串,直到找到一个匹配
import re
pattern='hello'
s='hello python'
# m=re.search(pattern,s)
m=re.match(pattern,s)
print(m)
print(m.group())
pattern='love'
s='I love you'
m=re.match(pattern,s)
print('使用match进行匹配',m)
o=re.search(pattern,s)
print('使用search进行匹配',o)
匹配多个字符串
search 方法搜索一个字符串,要想搜索多个字符串,如搜索 aa、bb 和 cc,最简单的方法是在文本模式字符串中使用择一匹配符号(|)。择一匹配符号和逻辑或类似,只要满足任何一个,就算匹配成功。
import re
pattern='aa|bb|cc'
s='aa'
o=re.match(pattern,s)
print(o)
s='bb'
o=re.match(pattern,s)
print(o)
s='my name is cc'
o=re.search(pattern,s)
o=re.match(pattern,s)
print(o)
print('匹配0-100之间所有的数字')
#匹配0-100之间所有的数字 0-99|100
pattern=r'[1-9]?\d$|100$'
s='1'
s='11'
s='99'
s='100'
s='1000'
o=re.match(pattern,s)
print(o)
分组
如果一个模式字符串中有用一对圆括号括起来的部分,那么这部分就会作为一组,可以 通过 group 方法的参数获取指定的组匹配的字符串。当然,如果模式字符串中没有任何用圆 括号括起来的部分,那么就不会对待匹配的字符串进行分组。
字符 | 功能 |
---|---|
(ab) | 将括号中的字符作为一个分组 |
\num | 引用分组 num 匹配到的字符串 |
(?p) | 分别起组名 |
(?p=name) | 引用别名为 name 分组匹配到的字符串 |
'''
(ab) 将括号中的字符作为一个分组
\num 引用分组num匹配到的字符串
(?p<name>) 分别起组名
(?p=name) 引用别名为name分组匹配到的字符串
'''
import re
print('匹配座机号码')
#匹配座机号码 区号{3,4}-电话号码{5,8} 010-43222 0432-447727
pattern=r'\d{3,4}-[1-9]\d{4,7}$'
pattern=r'(\d{3,4})-([1-9]\d{4,7}$)'
s='010-786545'
o=re.match(pattern,s)
print(o)
print(o.group())
print(o.group(1))
print(o.group(2))
# print(o.groups())
# print(o.groups()[0])
# print(o.groups()[1])
print('匹配出网页标签内的数据')
# pattern=r'<.+><.+>.+</.+></.+>'
pattern=r'<(.+)><(.+)>.+</\2></\1>'
# s='<html><head>head部分</head></html>'
s='<html><title>head部分</head></body>'
o=re.match(pattern,s)
print(o)
#<body><h1><div><div></div></div></h1></body>
print('(?P<name>) 分别起组名')
pattern=r'<(?P<k_html>.+)><(?P<k_head>.+)>.+</(?P=k_head)></(?P=k_html)>'
s='<html><head>head部分</head></html>'
s='<html><title>head部分</head></body>'
o=re.match(pattern,s)
print(o)
使用分组要了解如下几点:
1、只有圆括号括起来的部分才算一组,如果模式字符串中既有圆括号括起来的部分, 也有没有被圆括号括起来的部分,那么只会将被圆括号括起来的部分算作一组,其它的部分忽略。
2、 用 group 方法获取指定组的值时,组从 1 开始,也就是说,group(1)获取第 1 组的值,group(2)获取第 2 组的值,以此类推。
3、groups 方法用于获取所有组的值,以元组形式返回。所以除了使用 group(1)获取第 1 组的值外,还可以使用 groups()[0]获取第 1 组的值。获取第 2 组以及其它组的值的方式类似
sub 和 subn 搜索与替换
sub 函数和 subn 函数用于实现搜索和替换功能。这两个函数的功能几乎完全相同,都是将某个字符串中所有匹配正则表达式的部分替换成其他字符串。用来替换的部分可能是一个字符串,也可以是一个函数,该函数返回一个用来替换的字符串。sub 函数返回替换后的结果,subn 函数返回一个元组,元组的第 1 个元素是替换后的结果,第 2 个元素是替换的总数。语法格式如下:
re.sub(pattern, repl, string, count=0, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
repl | 替换的字符串,也可为一个函数 |
string | 要被查找替换的原始字符串 |
count | 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配 |
import re
phone='2004-959-559 # 这是一个国外电话号码'
#将phone中的注释去掉
pattern=r'#.*$'
result=re.sub(pattern,'',phone)
print('sub:',result)
pattern=r'#\D*'
result=re.sub(pattern,'',phone)
print('sub:',result)
result=re.subn(pattern,'',phone)
print(result)
print(result[0])
print(result[1])
compile函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:
re.compile(pattern[, flags])
参数 | 描述 |
---|---|
pattern | 一个字符串形式的正则表达式 |
flags | 可选,表示匹配模式,比如忽略大小写,多行模式等 |
import re
s='first123 line'
pattern=r'\w+'
regex=re.compile(pattern)
o=regex.match(s)
print(o)
findall 函数与finditer 函数
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的, 则返回空列表。语法格式如下:
这里是引用
findall(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 如下表列出正则表达式修饰符 - 可选标志 |
import re
s='first 1 second 2 third 3'
pattern=r'\w+'
result=re.findall(pattern,s)
print(result)
finditer 函数和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回
import re
s='first 1 second 2 third 3'
pattern=r'\w+'
result=re.finditer(pattern,s)
print(result)
for i in result:
print(i.group(),end='\t')
split 函数
plit 函数用于根据正则表达式分隔字符串,也就是说,将字符串与模式匹配的子字符串都作为分隔符来分隔这个字符串。split 函数返回一个列表形式的分隔结果,每一个列表元素都是分隔的子字符串。语法格式如下:
这里是引用
re.split(pattern, string[, maxsplit=0, flags=0])
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 如下表列出正则表达式修饰符 - 可选标志 |
贪婪模式和非贪婪
贪婪模式指 Python 里数量词默认是贪婪的,总是尝试匹配尽可能多的字符。非贪婪模式与贪婪相反,总是尝试匹配尽可能少的字符,可以使用"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
import re
v = re.match(r'(.+)(\d+-\d+-\d+)','This is my tel:133-1234-1234')
print(v.group(1))
print(v.group(2))
v = re.match(r'(.+?)(\d+-\d+-\d+)','This is my tel:133-1234-1234')
print(v.group(1))
print(v.group(2))
v= re.match(r'abc(\d+)','abc123')
print(v.group(1)) #123
#非贪婪模式
v= re.match(r'abc(\d+?)','abc123')
print(v.group(1)) #1