正则表达式
正则表达式(Regular Expression)用于描述一种字符串的匹配模式(Pattern),它可以用来检查一个字符串是否包含某个子串,也可以用于从字符串中提起匹配的子串,或者对字符串中匹配到的子串执行替换操作。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式
re 模块使 Python 语言拥有全部的正则表达式功能
re.compile(pattern, flags=0)
作用: 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象
示例:
In [1]: import re
In [2]: re.compile('', re.I)
Out[2]: re.compile(r'abc', re.IGNORECASE|re.UNICODE)
In [3]: type(re.compile(r'abc', re.I))
Out[3]: _sre.SRE_Pattern
re.match() 和 re.search()函数
函数语法:
re.match(pattern, string, flags=0)
re.search(pattern, string, flags=0)
语法 | 描述 | 返回对象 |
---|---|---|
re.match(pattern, string, flags=0) | 从字符串的起始位置来匹配模式,如果不是起始位置匹配成功的话,match()就返回none | _sre.SRE_Match/None |
re.search(pattern, string, flags=0) | 扫描整个字符串并返回第一个成功的匹配 | _sre.SRE_Match/None |
refindall(pattern, string, flags=0) | 扫描整个字符串,并返回所有匹配pattern的组成的列表 | [] |
re.finditer(pattern, string,flags=0) | 扫描整个字符串,并返回所有匹配pattern的组成的迭代器 | _sre.SRE_Match/None |
re.fullmatch(pattern, string, flags=0) | 整个字符串能匹配pattern | _sre.SRE_Match/None |
函数参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等 - 可选标志 |
示例:
# pattern 在起始位置
m1 = re.match('www', 'www.baidu.com')
print(m1.group()) # www
# pattern 在起始位置
m2 = re.match(r'bai', 'www.baidu.com')
print(m2) # None
#
m3 = re.search(r'bai', 'www.baidu.com') # <_sre.SRE_Match object; span=(4, 7), match='bai'>
print(m3)
# 多个匹配对象
m4 = re.search(r'ba', 'www.baidu.ba.com') # <_sre.SRE_Match object; span=(4, 6), match='ba'>
print(m4)
# 不存在
m5 = re.search(r'bad', 'www.baidu.ba.com') # None
print(m5)
string = '12a34bc560jf3dd45842'
# 返回列表
m6 = re.findall(r'\d+', string)
print(m6) # ['12', '34', '560', '3', '45842']
# 返回迭代器
m6 = re.finditer(r'\d+', string)
print(m6)
for e in m6:
print(e)
'''
# 迭代器返回内容,如下
<callable_iterator object at 0x00000229385DA9E8>
<_sre.SRE_Match object; span=(0, 2), match='12'>
<_sre.SRE_Match object; span=(3, 5), match='34'>
<_sre.SRE_Match object; span=(7, 10), match='560'>
<_sre.SRE_Match object; span=(12, 13), match='3'>
<_sre.SRE_Match object; span=(15, 20), match='45842'>
'''
string2 = 'abs123'
m7 = re.fullmatch(r'\w{3}\d{3}', string2, re.I)
print(m7) # <_sre.SRE_Match object; span=(0, 6), match='abs123'>
替换和分割
替换:
语法:re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 匹配的正则表达式
- repl : 被替换的字符串,或者函数
- string : 要被查找替换的字符串
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
- flags : 编译时用的匹配模式,数字形式
- 前三个为必选参数,后两个为可选参数
# re.sub() repl 是字符串
string3 = '我正在学习python的re模块'
str3 = re.sub(r'\w+', 'java', string3, 1, re.A)
print(str3) # 我正在学习java的re模块
def fun(matched):
"""
:param matched: 匹配对象
:return:
"""
value = "<<"+matched.group(0)+">>"
return value
# repl 是函数
str4 = re.sub(r'\w+', fun, string3, 1, re.A)
print(str4) # 我正在学习<<python>>的re模块
分割
语法:re.split(pattern, string, maxsplit=0, flags=0)
参数:
- pattern: 匹配的正则表达式
- string:要分割的字符串
- maxsplit: 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数
- flags: 旗标
# re.split()
print(re.split(r'\s', 'JAVA, PYTHON, GO, CSS, SPACE'))
# ['JAVA,', 'PYTHON,', 'GO,', 'CSS,', 'SPACE']
# 没有匹配到则不分割
print(re.split('a*', 'hello world'))
# ['hello world']
re.purge(): 清除正则表达式的缓存
re.escape(pattern): 对模式中除ASCII字符,数值,下划线(_)之外的字符进行转义
print(re.escape(r'abcs.09087_43-0032:\d\g'))
# abcs\.09087_43\-0032\:\\d\\g
_sre.SRE_Pattern 正则表达式对象
re.compile()的返回值
该对象的match(),search(), findall(), finditer(),fullmatch()方法可以额外指定pos 和endpos两个参数;
参数:
pos: 目标字符从pos开始
endpos:目标字符从endpos结束
示例:
# 编译得到正则表达式
pa = re.compile('bai')
string4 = 'www.baidu.com'
# 调用match方法
print(pa.match(string4, 4).group()) # bai
正则表达式旗标
旗标 | 行内旗标 | 描述 |
---|---|---|
re.A | (?a) | 控制\w,\b,\d,\s及其大写模式只匹配ASCII字符,而不匹配所有的Unicode字符 |
re.I | (?i) | 使正则表达式匹配式不区分大小写 |
re.L | (?L) | 根据当前区域设置使pattern匹配时不区分大小写,只对bytes模式起作用 |
re.M | (?m) | 多行模式的旗标 |
re.S | (?s) | 让点(.)能匹配所有包括换行符在内的所有字符 |
re.X | (?x) | 允许分行书写正则表达式,也允许为正则表达式添加注释 |
re.U | 控制\w,\b,\d,\s及其大写模式只匹配Unicode字符 |
正则表达式的模式
模式 | 描述 |
---|---|
$ | 匹配字符串的末尾 |
^ | 匹配字符串的开头 |
. | 匹配除换行符\n之外的所有字符 |
[…] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’,[a-c] 匹配‘a’, ‘b’, ‘c’ |
[^…] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符 |
* | 匹配0个或多个的表达式 |
+ | 匹配1个或多个的表达式 |
? | 匹配0个或1个的表达式 |
{n} | 匹配n个前面表达式。例如,"o{2}“不能匹配"Bob"中的"o”,但是能匹配"food"中的两个o |
{ n,} | 精确匹配n个前面表达式。例如,"o{1,}“等价于"o+”。"o{0,}“则等价于"o*” |
{ n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a| b | 匹配a或b |
(exp) | 匹配括号内的表达式,也表示一个组,自动捕获,引用\1, |
(?:exp) | 匹配括号内的表达式,也表示一个组,不捕获, |
(?P<name>exp) | 匹配括号内的表达式,也表示一个组,捕获 的内容命名为name |
(?P=name) | 通过名字引用匹配捕获的表达式 |
(?<=exp) | 括号中的子模式必须出现在匹配内容的左侧 |
(?=exp) | 括号中的子模式必须出现在匹配内容的右侧 |
(?<!exp) | 括号中的子模式必须不出现在匹配内容的左侧 |
(?!exp) | 括号中的子模式必须不出现在匹配内容的右侧 |
(?#comment) | 注释 |
(?aiLumsux) | 行内旗标,作用于整个表达式 |
(?-aiLumsux) | 行内逆旗标,作用于整个表达式 |
(?aiLumsux:exp) | 行内旗标,作用于()内 |
(?-aiLumsux:exp) | 行内逆旗标,作用于()内 |
\w | 匹配数字字母下划线 |
\W | 匹配非数字字母下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f] |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9] |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串 |
\z | 匹配字符串结束 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\B | 匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’ |
\ | 用于转义下一个字符 |
| | 指定两者之间选一个 |
随机生成练习数据
参考:python核心编程
from random import randrange, choice, randint
from string import ascii_lowercase as lc
from time import ctime
def gendata():
tlds = ('com', 'edu', 'net', 'org', 'cn')
for i in range(randrange(5, 11)):
dtint = randrange(2**32-1)
dtstr = ctime(dtint)
llen = randrange(4, 8)
login = ''.join(choice(lc) for j in range(llen))
dlen = randrange(llen, 13)
dom = ''.join(choice(lc) for j in range(dlen))
ulen = randrange(dlen, 15)
unich = ''.join(chr(randint(0x4E00, 0x9FA5))for j in range(ulen))
print('%s::%s@%s.%s::%d-%d-%d::%s' % (dtstr, login, dom, choice(tlds), dtint, llen, dlen, unich))
if __name__ == '__main__':
p = gendata()
data = 'Wed Mar 30 20:45:49 2005::tpiwjtf@gexgahxq.net::1112186749-7-8::慍襋呩奓琓鉑睓膪蔦'
# 匹配 开头的星期天数
print(re.match(r'^(\w{3})', data, re.I).group(1)) # Wed
# 匹配月份和日期
p = re.compile(r'(\w{3,}[\s]\d{0,2})', flags=re.I)
print(p.match(data, pos=4)) # <_sre.SRE_Match object; span=(4, 10), match='Mar 30'>
#匹配年份
s = re.compile(r'(?<=\d{2}:\d{2}:\d{2}\s)\d{4}(?=::\w+)')
st = s.search(data)
if st is not None:
print(st.group(), st.span()) # 2005 (20, 24)
# 匹配后面的数字1112186749-7-8
print(re.search(r'(?P<number>\d+-\d+-\d+)', data)) # <_sre.SRE_Match object; span=(48, 62), match='1112186749-7-8'>
# 匹配中文
print(re.findall(r'[\u4e00-\u9fa5\,\。]+', data)) # ['慍襋呩奓琓鉑睓膪蔦']
data = """
Guido van Rossum
Tim Peters
Alex Martelli
Just Van Rossum
Raymond Hettinger
"""
print(re.findall(r'\w+(?= van Rossum)', data, re.I)) # ['Guido', 'Just']