1.1 正则
正则表达式(Regular Expression),在代码中是预先定义好的一个规则串,这个规则串可以匹配,查找,替换那些符合规则的文本。
1.2 正则表达式字符串
正则表达式的字符串由普通字符和元字符组成。
- 普通字符
按字面的意义表示的字符,如 abcd
等,表示字符本身的意义。
- 元字符
用于描述其它字符的特殊字符,它由基本元字符和普通字符组成。元字符是预先定义好的一些特定字符,如:\w+
等
1.3 元字符
基本元字符:
字符 | 说明 |
---|---|
\ | 转义符 |
. | 表示任意一个字符 |
+ | 表示重复一次或多次 |
* | 表示重复零次或多次 |
? | 表示重复零次或一次 |
| | 选择符号,表示或关系 |
{} | 定义量词,表示重复指定次数 |
[] | 定义字符集(字符范围) |
() | 定义分组 |
^ | 表示字符集中的取反,或匹配一行的开始 |
$ | 表示匹配一行的结束 |
1.4 转义
对于元字符,如果想要表示字符本身的意义,比如.
就表示点,而不是表示任意字符,则需要转义:
\.
元字符前面加一个斜杠,就表示元字符字符本意。
1.5 开始与结束
^
表示一行的开始, $
表示一行的结束
import re
email = 'myccloves@163.com'
regexp = r'^\w+@.*com$'
result = re.match(regexp, email)
print(result) # 匹配
\w
表示[a-zA-z0-9_]
这个正则表示以字母,或数字,或下划线组成字符串开头(重复),后跟一个@,后跟任意字符,以com结尾
1.6 字符集
[]
把需要匹配的字符放到方括号里,比如:[Aa]
表示匹配A或者a
import re
email = 'myccloves@163.com'
regexp = r'[coes]ve'
result = re.search(regexp, email)
print(result) # 匹配: cve, ove, eve, sve 这里匹配到了ove
1.6.1 字符集取反
表示不在字符集中的字符
[^字符]
比如:[^a]
表示除了a,其它的字符都匹配。
import re
email = 'myccloves@163.com'
regexp = r'[^0123456789]+'
result = re.search(regexp, email)
print(result) # 匹配到了myccloves@
1.6.2 字符集区间
表达了一个范围:[开始-结束]
, 比如:[a-z]
匹配字符a到字符z之间所有的字符。
import re
email = 'myccloves@163.com'
regexp = r'[a-z]+'
result = re.search(regexp, email)
print(result) # 匹配myccloves
1.7 预定义字符
预先定义好的一些正则字符
字符 | 说明 |
---|---|
\n | 换行 |
\r | 回车 |
\f | 换页 |
\t | 水平制表 |
\v | 垂直制表 |
\s | 空白符,相当于 [\t\n\r\f\v] |
\S | 非空白符,相当于 [^\s] |
\d | 数字,相当于[0-9] |
\D | 非数字,相当于[^0-9] |
\w | 匹配字母,数字,下划线。字母不限于英文 |
\W | 等价于[^\w] |
\b | 单词边界 |
\B | 等价于 [^\b] |
1.8 量词
用于表示字符或字符串重复的次数。
字符 | 说明 |
---|---|
? |
出现零次或一次 |
* |
出现零次或多次 |
+ |
出现一次或多次 |
{n} |
出现n次 |
{n,m} |
出现n次,但不超过m次,m>次数>=n |
{n,} |
至少出现n次 |
import re
string = '87654321'
regexp = r'\d{3,4}'
result = re.search(regexp, string)
print(result) # 匹配8765
1.8.1 贪婪和懒惰
默认是贪婪的,尽可能多的匹配,而懒惰最少匹配。懒惰匹配在量词后面加一个问号。
import re
string = '87654321'
regexp = r'\d{3,5}?'
result = re.search(regexp, string)
print(result) # 匹配876,按最少的匹配。
如:
import re
string = '<h1>hello</h1><h2>welcome!</h2>'
regexp = r'<h.>.*</h.>'
result = re.search(regexp, string)
print(result) # 匹配所有,贪婪的
regexp = r'<h.>.*?</h.>'
result = re.search(regexp, string)
print(result) # 只匹配<h1>hello</h1>, 尽可能少的匹配
1.9 分组
之前的量词只能重复一个字符,如果想让一个字符串作为整体使用量词,可以用分组。
分组也称为子表达式。
import re
string = 'abcabc1234151234'
regexp = r'(abc){2}' # 表示abc重复2次:abcabc
result = re.search(regexp, string)
print(result)
import re
string = '0437-6337700'
regexp = r'(\d{4})-(\d{7})' # 有两个组
result = re.search(regexp, string)
print(result) # 匹配成功, 输出Match对象
print(result.group()) # 0437-6337700
print(result.group(1)) # 0437
print(result.group(2)) # 6337700
print(result.groups()) # ('0437', '6337700')
group(1) 表示取出第一个组匹配的数据,group(2)表示取出第二个组匹配的数据
groups() 返回所有组中的内容,返回一个元组。
1.9.1 分组的命名
(?P<组名> ...)
分组命名之后,可以通过组名来返回匹配内容。
import re
string = '0437-6337700'
regexp = r'(?P<area>\d{4})-(?P<tel>\d{7})' # 有两个组
result = re.search(regexp, string)
print(result.group('area')) # 0437
print(result.group('tel')) # 6337700
1.9.2 反向引用分组
下例中的:\1
表示引用第一个分组,依此类推。
import re
string = '<h1>aaaa</h1>'
regexp = r'<(\w+)>.*</\1>+' # \w是啥,后面的\1就是啥。比如:h1后面的\1就是h1
result = re.search(regexp, string)
print(result)
1.9.3 非捕获分组
有时候不需要捕获某个分组的内容,但又想使用分组的特性,可以使用非捕获组。
string = '1.txt,2.txt,3.txt,4.txt'
regexp = r'\d(\.txt)'
result = re.findall(regexp, string)
# 得到的都是分组中的内容
print(result) # ['.txt', '.txt', '.txt', '.txt']
# 需要将小()中的内容作为一个整体匹配,前面加?:变成非捕获分组
result = re.findall(r'\d(?:\.txt)', string)
print(result) # ['1.txt', '2.txt', '3.txt', '4.txt']
2.1 re模块
re模块内置正则表达式模块。
2.1.1 search和match函数
search(pattern, string, flags=0)
match(pattern, string, flags=0)
这两个函数都用来进行第一次匹配,如果匹配返回Match对象,不匹配返回None
区别:
- search 在字符串中查找匹配
- match 在字符串开头进行匹配
import re
s = "abc12345abc54321"
m = re.search(r'\d+', s)
print(type(m)) # re.Match对象
print(m.group()) # 匹配的数据
print(m.start()) # 3 匹配的开始位置
print(m.end()) # 8 匹配的结束位置
print(m.span()) # 匹配的开始和结束位置,以元组返回
对于match对象,如果开头不匹配直接返回None
import re
s = "abc12345abc54321"
m = re.match(r'\d+', s)
print(m) # None
2.1.2 findall和finditer函数
findall(pattern, string, flags=0)
finditer(pattern, string, flags=0)
这两个函数返回所有匹配(search,match只返回第一次匹配), 匹配失败返回空列表
区别:
- findall 如果匹配成功返回匹配的数据
- finditer 如果匹配成功返回可迭代对象,遍历每个Match元素对象,得到匹配数据
import re
s = "abc12345abc54321"
m = re.findall(r'\d+', s)
print(m) # ['12345', '54321']
it = re.finditer(r'\d+',s)
for m in it:
print(type(m))
print(m.group())
2.1.3 split函数
用于字符串分割,返回列表。
split(pattern, string, maxsplit=0, flags=0)
maxsplit表示最多分割几次
import re
s = "abc12345abc54321sdfsdfs33sadfs22"
result = re.split(r'\d+', s, maxsplit=1)
print(result) # ['abc', 'abc54321sdfsdfs33sadfs22']
import re
s = "abc12345abc54321sdfsdfs33sadfs22"
result = re.split(r'\d+', s)
print(result) # ['abc', 'abc', 'sdfsdfs', 'sadfs', '']
2.1.4 sub函数
用于字符串替换
sub(pattern, repl, string, count=0, flags=0)
count表示替换几次
import re
s = "abc12345abc54321sdfsdfs33sadfs22"
result = re.sub(r'\d+', ',', s, count=3)
print(result) # abc,abc,sdfsdfs,sadfs22
3.1 编译正则表达式
编译的正则可以重复使用,减少正则表达式的解析和验证,提高效率。
re.compile(pattern, flags=0)
这个函数返回一个Pattern对象,Pattern对象中调用相应的方法实现匹配,替换,分割等。
方法 |
---|
search(self, /, string, pos=0, endpos=9223372036854775807) |
match(self, /, string, pos=0, endpos=9223372036854775807) |
findall(self, /, string, pos=0, endpos=9223372036854775807) |
finditer(self, /, string, pos=0, endpos=9223372036854775807) |
sub(self, /, repl, string, count=0) |
split(self, /, string, maxsplit=0) |
这些功能同re模块中的函数类似,前四个pos表示开始位置,endpos表示结束位置,从这个范围内进行匹配。
import re
s = "abc12345abc54321sdfsdfs33sadfs22"
p = re.compile(r'\d+')
result = p.match(s, pos=3)
print(result.group()) # 12345
3.1.2 编译标志
标志 | 说明 |
---|---|
re.I, re.IGNORECASE | 不区分大小写 |
re.L, re.LOCALE | 根据所使用的本地语言环境通过\w,\W,\b,\B,\s,\S实现匹配 |
re.M, re.MULTILINE | 多行模式,对于^和$产生影响。 |
re.S, re.DOTALL | . (点号)一般匹配除了\n的所有字符,标记后点号匹配所有 |
re.X, re.VERBOSE | 详细模式,可以添加注释,允许有空格,换行 |
import re
s = """1234
5678
abc
90"""
print(re.findall(r'^\d+', s)) # ['1234']
print(re.findall(r'^\d+', s, re.MULTILINE)) # ['1234', '5678', '90']
如果有多个标志可以用|串联。
import re
s = "abc123\nAbc456\nABc789"
result = re.findall(r'^abc\d+', s, re.IGNORECASE | re.MULTILINE)
print(result) # ['abc123', 'Abc456', 'ABc789']
标签:匹配,string,re,PYTHON,正则表达式,result,print,regexp
From: https://www.cnblogs.com/three-sheep/p/17250739.html