# -*- coding: utf-8 -*-
import re
import os
#------------------------------------- re(正则表达式)模块 --------------------------------
#-----------------------------------------------------------------------------------------------------
#------------------------------------- 概念 --------------------------------
#-----------------------------------------------------------------------------------------------------
'''
正则表达式:又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),
计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,
正则表达式通常被用来检索、替换那些符合某个模式的文本。
Python通过re模块提供对正则表达式的支持。使用re的一般步骤是先使用re.compile()函数,将正则表达式的字符串形式编译为Pattern实例,
然后使用Pattern实例处理文本并获得匹配结果(一个Match实例),最后使用Match实例获得信息,进行其他的操作。
'''
#-----------------------------------------------------------------------------------------------------
#------------------------------------- 元字符 --------------------------------
#-----------------------------------------------------------------------------------------------------
'''
元字符(Meta-Characters)是正则表达式中具有特殊意义的专用字符,用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。
. 表示任意字符
[] 用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字符集,对于字符集中的字符可以理解成或的关系。
^ 如果放在字符串的开头,则表示取非的意思。[^5]表示除了5之外的其他字符。而如果^不在字符串的开头,则表示它本身。
\ 可以看成转意字符(同C语言)
| 表示或 左右表达式各任意匹配一个,从左边先匹配起,如果成功,则跳过右边的表达式.如果没有放在()中,则范围是整个表达式
具有重复功能的元字符
* 对于前一个字符重复"0~无穷"次
+ 对于前一个字符,重复"1~无穷"次
? 对于前一个字符,重复"0~1"次
{m,n} 对于前一个字符,重复"m~n"次,其中{0,}等价于*, {1,}等价于+, {0,1}等价于?
{m,n}? 对前一个字符,重复"m~n"次,非贪婪模式
{m} 对前一个字符,重复"m"次
\d 匹配十进制数, 等价于[0-9]
\D 匹配任意非数字字符, 等价于[^0-9]
\s 匹配任何空白字符, 等价于[<空格>\f\n\r\t\v]
\S 匹配任何非空白字符, 等价于[^<空格>\f\n\r\t\v]
\w 匹配任意单词字符(构成单词的字符,字母,数字,下划线), 等价于[a-zA-Z0-9_]
\W 匹配任意非单词字符(构成单词的字符,字母,数字,下划线), 等价于[^a-zA-Z0-9_]
\A 匹配字符串的开头
\Z 匹配字符串的结尾
以下是(?...)系列 这是一个表达式的扩展符号。'?'后的第一个字母决定了整个表达式的语法和含义,除了(?P...)以外,表达式不会产生一个新的组。
(?iLmsux) 'i'、'L'、'm'、's'、'u'、'x'里的一个或多个字母。表达式不匹配任何字符,但是指定相应的标志:re.I(忽略大小写)、re.L(依赖locale)、re.M(多行模式)、re.S(.匹配所有字符)、re.U(依赖Unicode)、re.X(详细模式)。
(?P<name>...) 除了原有的编号外再额外指定一个别名
(?P=name...) 引用别名name分组找到的字符串
(?#...) #后面的将被作为注释, 相当于表达式中的注释
(?:...) 匹配内部的RE所匹配的内容,但是不建立组。
(?=...) 如果 ... 匹配接下来的字符,才算匹配,但是并不会消耗任何被匹配的字符,这个叫做“前瞻断言”。
(?!...) 如果 ... 不匹配接下来的字符,才算匹配, 和(?=...)相反
(?<=...) 只有当当前位置之前的字符串匹配 ... ,整个匹配才有效,这叫“后顾断言”。
(?<!...) 只有当当前位置之前的字符串不匹配 ...,整个匹配才有效, 和(?<=...)相反
'''
#-------------------- . -----------------
"""
. 在默认模式下,匹配除换行符外的所有字符。在DOTALL模式下,匹配所有字符,包括换行符。
"""
s = 'hello\nworld!'
m = re.findall('.', s)
print(m)
#['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '!']
m1 = re.findall('.', s, re.DOTALL)
print(m1)
#['h', 'e', 'l', 'l', 'o', '\n', 'w', 'o', 'r', 'l', 'd', '!']
s2 = ''
m2 = re.findall('.', s2, re.DOTALL)
print(m2)
#[]
#-------------------- [] -----------------
s = 'hello world!'
m = re.findall('[adf]', s) #字符集表示法, 匹配a或d或f的字符
print(m)
#['d']
n = re.findall('[a-e]', s) #区间表示法, 匹配a~e的字符
print(n)
#['e', 'd']
#-------------------- ^ -----------------
"""
^ "^abc" 放在字符串abc的开头表示匹配以abc开始的字符串
"ab^c" 暂时不明
"abc^" 暂时不明
[^abc] 放在[]中的开头表示取反, 表示非abc之外的其它字符
[ab^c] 中的非开头表示普通字符^
[abc^] 放在在[]内尾位,就只代表普通字符^
"""
s = 'hello world! [^_^]'
m = re.findall('^hel', s)
print(m)
#['hel']
m1 = re.findall('h^el', s)
print(m1)
#[]
m2 = re.findall('hel^', s)
print(m2)
#[]
m3 = re.findall('[^hel]', s)
print(m3)
#['o', ' ', 'w', 'o', 'r', 'd', '!', ' ', '[', '^', '_', '^', ']']
m4 = re.findall('[h^el]', s)
print(m4)
#['h', 'e', 'l', 'l', 'l', '^', '^']
m5 = re.findall('[hel^]', s)
print(m5)
#['h', 'e', 'l', 'l', 'l', '^', '^']
#-------------------- \ -----------------
"""
\ 转意字符
"""
s = 'hello world!^_^'
m = re.findall('[^a-h]', s) #匹配非a~h的所有字符
print(m)
#['l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', '!', '^', '_', '^']
m1 = re.findall('[\^a-h]', s) #^被转意了,使之变成了普通字符的意思, 匹配非a~h和^字符
print(m1)
#['h', 'e', 'd', '^', '^']
#-------------------- * -----------------
"""
* 匹配0~无穷个前面的字符, 如何只想匹配*字符,可以写\*或者[*], \*等价于[*]
"""
s = 'hello world! yes! ^_^'
m = re.findall('el*', s) #匹配el(l数量为0~无穷)
print(m)
#['ell', 'e']
s = '*****hello***'
m = re.findall('[*]\*', s) #匹配查找**字符串
print(m)
#['**', '**', '**']
#-------------------- ? -----------------
"""
? 匹配0~1个前面的字符
"""
s = 'hello world! yes! ^_^'
m = re.findall('el?', s) #匹配el(l数量为0~1)
print(m)
#['el', 'e']
#-------------------- + -----------------
"""
+ 匹配1~无穷个前面的字符
"""
s = 'hello world! yes! ^_^'
m = re.findall('el+', s) #匹配el(l数量为1~无穷)
print(m)
#['el']
#-------------------- | -----------------
"""
| 表示或 左右表达式各任意匹配一个,从左边先匹配起,如果成功,则跳过右边的表达式.如果没有放在()中,则范围是整个表达式
"""
s = 'hello world! yes! ^_^'
m = re.findall("e|o", s)
print(m)
#['e', 'o', 'o', 'e']
#-------------------- {} -----------------
"""
{m} 表示前面的正则表达式m次copy
{m} 表示前面的正则表达式m次copy, 由于只有一个m,所以等价于{m}?, 所以一般不这么写
{m,n} 表示前面的正则表达式m~n次copy, 尝试匹配尽可能多的copy
{m,n}? 表示前面正则表达式的m到n次copy,尝试匹配尽可能少的copy
"""
s = 'hello world! yes! ^_^'
m = re.findall("e{0,}l{1,6}o{1}", s)
print(m)
#['ell', 'l']
s = 'aaaaaaa'
m = re.findall('a{2}', s)
print(m)
#['aa', 'aa']
m = re.findall('a{2}?', s)
print(m)
#['aa', 'aa']
m = re.findall('a{2,5}', s)
print(m)
#['aaaaa', 'aa']
m = re.findall('a{2,5}?', s)
print(m)
#['aa', 'aa', 'aa']
#-------------------- () -----------------
"""
() 表示一组, 同C语言
"""
s = 'hello world! yes! ^_^'
m = re.findall('[(l+)|(es)]', s) #匹配el(l数量为0~无穷)
print(m)
#['e', 'l', 'l', 'l', 'e', 's']
#-------------------- $ -----------------
"""
$ 匹配字符串末尾,在多行(MULTILINE)模式中,匹配每一行的末尾.
"""
s = 'hello foo1\nworld foo2\n'
m = re.findall('foo.$', s) #匹配以foo.结尾的字符串foo.
print(m)
#['foo2']
s = 'hello foo1\nworld foo2\n'
m = re.findall('foo.$', s, re.M) #多行模式re.M下, 匹配每行以foo.结尾的字符串foo.
print(m)
#['foo1', 'foo2']
#-------------------- \A -----------------
"""
\A 匹配字符串开始.
"""
s = 'hello world'
m = re.findall('\Ahell', s)
print(m)
#['hell']
m = re.findall('\Aell', s)
print(m)
#[]
#-------------------- \Z -----------------
"""
\Z 匹配字符串结尾.
"""
s = 'hello world'
m = re.findall('ld\Z', s)
print(m)
#['ld']
m = re.findall('orl\Z', s)
print(m)
#[]
#-------------------- (?P<name>...) -----------------
"""
(?P<name>...) 除了原有的编号外再额外指定一个别名
"""
m = re.match("(?P<first>\w+) (?P<second>\w+)", "hello world") #匹配到第1个起别名'first',匹配到第2个起别名second
g = m.groupdict()
print(g)
#{'second': 'world', 'first': 'hello'}
print(g['first'])
#hello
#-------------------- \number -----------------
"""
\number 引用编号为number的分组找到的字符串
"""
m = re.findall('(\d)he(\d)llo(\d)', '1he5llo2 3world4, 1he5llo5 3world4')
print(m)
#[('1', '5', '2'), ('1', '5', '5')]
m = re.findall('\dhe\dllo\2', '1he5llo2 3world4, 1he5llo5 3world4')
print(m)
#[]
#-------------------- (?iLmsux) -----------------
"""
'i'、'L'、'm'、's'、'u'、'x'里的一个或多个字母。表达式不匹配任何字符,但是指定相应的标志:
re.I(忽略大小写)、re.L(依赖locale)、re.M(多行模式)、re.S(.匹配所有字符)、re.U(依赖Unicode)、re.X(详细模式)。
"""
s = 'hello foo1\nworld foo2\n'
m = re.findall('foo.$', s)
print(m)
#['foo2']
m = re.findall('(?m)foo.$', s) #等价于m = re.findall('foo.$', s, re.M)
print(m)
#['foo1', 'foo2']
s1 = 'HELLO WORLD'
m = re.findall('(?i)[a-z]', s1) #等价于m = re.findall('[a-z]', s, re.)
print(m)
#['H', 'E', 'L', 'L', 'O', 'W', 'O', 'R', 'L', 'D']
#-------------------- (?P=name...) -----------------
"""
(?P=name...) 引用别名name分组找到的字符串
"""
#匹配到第1个起别名'first'+空格+匹配到第2个起别名second+逗号+别名first找到的结果作为搜索表达式的一部分
m = re.match("(?P<first>\w+) (?P<second>\w+),(?P=first)", "hello world,hello world")
g = m.groupdict()
print(g)
#{'second': 'world', 'first': 'hello'}
m = re.match("(?P<first>\w+) (?P<second>\w+) (?P<third>(?P=first))", "hello world hello world")
g = m.groupdict()
print(g)
#{'second': 'world', 'third': 'hello', 'first': 'hello'}
#-------------------- (?#...) -----------------
"""
(?#...) #后面的将被作为注释, 相当于表达式中的注释
"""
s = 'hello1 #12345'
m = re.findall('he\w+\d', s)
print(m)
#['hello1']
m = re.findall('he\w+(?#前面这个表达式he\w+意思是he和任意单词字符的组合)\d', s)
print(m)
#['hello1']
#-------------------- (?=...) -----------------
"""
(?=...) 如果 ... 匹配接下来的字符,才算匹配,但是并不会消耗任何被匹配的字符。
例如 Isaac (?=Asimov) 只会匹配后面跟着 'Asimov' 的 'Isaac ',这个叫做“前瞻断言”。
"""
s = 'hellooookl world, help'
g = re.findall('hel', s)
print(g)
#['hel', 'hel']
g = re.findall('hel(?=lo)', s) #遍历查找hel, (?=lo)位置跟着lo的才算
print(g)
#['hel']
#-------------------- (?!...) -----------------
"""
(?!...) 和 (?!=...)正好相反。
"""
s = 'hello world, help'
g = re.findall('hel(?!lo)', s) #遍历查找hel, (?=lo)位置没有跟着lo的才算
print(g)
#['hel']
g = re.findall('hel(?!klo)', s) #遍历查找hel, (?=klo)位置没有跟着klo的才算
print(g)
#['hel', 'hel']
#-------------------- (?<=...) -----------------
"""
(?<=...) 只有当当前位置之前的字符串匹配 ... ,整个匹配才有效,这叫“后顾断言”。
"""
s = 'hhello world, hkelp'
g = re.findall('el', s) #遍历查找el
print(g)
#['el', 'el']
g = re.findall('(?<=h)el', s) #遍历查找el, (?<=h)位置跟着h的才算
print(g)
#['el']
#-------------------- (?<!...) -----------------
"""
(?<!...) 只有当当前位置之前的字符串不匹配 ... ,整个匹配才有效,和(?<=...)功能相反.
"""
s = 'hello world, hkelp'
g = re.findall('el', s) #遍历查找el
print(g)
#['el', 'el']
g = re.findall('(?<!h)el', s) #遍历查找el,(?<!h)的位置没有跟着h的才算
print(g)
#['el']
g = re.findall('(?<!m)el', s) #遍历查找el, (?<!m)的位置没有跟着m的才算
print(g)
#['el', 'el']
#-----------------------------------------------------------------------------------------------------
#------------------------------------- 数量词的贪婪模式与非贪婪模式 --------------------------------
#-----------------------------------------------------------------------------------------------------
"""
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),
总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",
将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
"""
s = 'abbbbb'
g = re.findall('ab+', s)
print(g)
#['abbbbb']
g = re.findall('ab+?', s)
print(g)
#['ab']
#-----------------------------------------------------------------------------------------------------
#------------------------------------- 反斜杠 --------------------------------
#-----------------------------------------------------------------------------------------------------
"""
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",
那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,
转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。
同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
"""
s = 'abc12\\df3g4h'
pattern = r'\d\\'
pattern_obj = re.compile(pattern)
g = re.findall(pattern_obj, s)
print(g)
#['2\\']
#-----------------------------------------------------------------------------------------------------
#------------------------------------- 函数部分 --------------------------------
#-----------------------------------------------------------------------------------------------------
#-------------------- re.compile(strPattern[, flag]) -----------------
"""
re.compile(strPattern[, flag]):
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。
第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M。
另外,你也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的。
可选值有:
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变'.'的行为
L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
a = re.compile(r'''\d + # the integral part
\. # the decimal point
\d * # some fractional digits''', re.X)
b = re.compile(r"\d+\.\d*")
re提供了众多模块方法用于完成正则表达式的功能。这些方法可以使用Pattern实例的相应方法替代,唯一的好处是少写一行re.compile()代码,
但同时也无法复用编译后的Pattern对象。如下面这个例子可以简写为:
"""
s = 'hello world'
p = re.compile('hello')
match = re.match(p, s)
if match:
print(match.group())
#hello
#上面例子等价于(可以简写为)
match = re.match('hello', 'hello world')
print(match.group())
#hello
#-------------------- re.match(pattern, string, flags=0) -----------------
"""
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。
属性:
string: 匹配时使用的文本。
re: 匹配时使用的Pattern对象。
pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,
返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
span([group]):
返回(start(group), end(group))。
expand(template):
将匹配到的分组代入template中然后返回。template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。\id与\g<id>是等价的;
但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0。
"""
match = re.match(r'(\w+) (\w+)(?P<sign>.*)', 'hello world!')
print(match.string)
#hello world!
print(match.re)
#<_sre.SRE_Pattern object at 0x100298e90>
print(match.pos)
#0
print(match.endpos)
#12
print(match.lastindex)
#3
print(match.lastgroup)
#sign
print(match.groups())
#('hello', 'world', '!')
print(match.group(0))
#hello world!
print(match.group(1, 2))
#('hello', 'world')
print(match.groupdict())
#{'sign': '!'}
print(match.start(2))
#6
print(match.end(2))
#11
print(match.span(2))
#(6, 11)
print(match.expand(r'\2 \1\3'))
#world hello!
#-------------------- re.search(pattern, string, flags=0) -----------------
"""
search对象是一次匹配的结果
属性和方法同re.match(pattern, string, flags=0),它俩的区别:
match()函数只检测RE是不是在string的开始位置匹配,
search()会扫描整个string查找匹配;
也就是说match()只有在0位置匹配成功的话才有返回,
如果不是开始位置匹配成功的话,match()就返回none。
"""
s = 'hello world, hellp'
print(re.match('hel', s).span())
#(0, 3)
print(re.match('ell', s))
#None
print(re.search('hel', s).span())
#(0, 3)
print(re.search('ell', s).span())
#(1, 4)
#-------------------- Pattern相关实例方法 -----------------
"""
Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找。
Pattern不能直接实例化,必须使用re.compile()进行构造。
Pattern提供了几个可读属性用于获取表达式的相关信息:
pattern: 编译时用的表达式字符串。
flags: 编译时用的匹配模式。数字形式。
groups: 表达式中分组的数量。
groupindex: 以表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。
"""
p = re.compile(r'(\w+) (\w+)(?P<sign>.*)', re.I)
print(p.pattern)
#(\w+) (\w+)(?P<sign>.*)
print(p.flags)
#2
print(p.groups)
#3
print(p.groupindex)
#{'sign': 3}
#-------------------- match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]) -----------------
"""
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]):
这个方法将从string的pos下标处起尝试匹配pattern;如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。
pos和endpos的默认值分别为0和len(string);re.match()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
注意:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'。
"""
s = 'hello world, help'
p = re.compile('hel')
m = p.match(s, 0, 10)
print(m.group())
#hel
m = p.match(s)
print(m.group())
#hel
m = re.match('hel', s)
print(m.group())
#hel
#-------------------- search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]) -----------------
"""
2.search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):
这个方法用于查找字符串中可以匹配成功的子串。从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象;
若无法匹配,则将pos加1后重新尝试匹配;直到pos=endpos时仍无法匹配则返回None。
pos和endpos的默认值分别为0和len(string));re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
"""
s = 'hello world, help'
p = re.compile('hel')
m = p.search(s, 0, 10)
print(m.group())
#hel
m = p.search(s)
print(m.group())
#hel
m = re.search('hel', s)
print(m.group())
#hel
#-------------------- split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]) -----------------
"""
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
"""
p = re.compile(r'\d+')
print(p.split('one1two2three3four4'))
#['one', 'two', 'three', 'four', '']
print(p.split('one1two2three3four4', 2))
#['one', 'two', 'three3four4']
print(re.split(r'\d+','one1two2three3four4'))
#['one', 'two', 'three', 'four', '']
print(re.split(r'\d+', 'one1two2three3four4', 2))
#['one', 'two', 'three3four4']
#-------------------- findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]) -----------------
"""
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):
搜索string,以列表形式返回全部能匹配的子串。re中的findall无法指定字符串搜索起止位置, pattern中的findall无法指定标记类型
"""
p = re.compile(r'\d+')
print(p.findall('one1two2three3four4'))
#['1', '2', '3', '4']
print(p.findall('one1two2three3four4', 10))
#['3', '4']
print(re.findall(r'\d+','one1two2three3four4'))
#['1', '2', '3', '4']
print(re.findall(r'\d+', 'one1two2three3four4', re.I))
#['1', '2', '3', '4']
#-------------------- finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]) -----------------
"""
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。re中的findall无法指定字符串搜索起止位置, pattern中的findall无法指定标记类型
"""
p = re.compile(r'\d+')
for m in p.finditer('one1two2three3four4'):
print(m.group())
#1
#2
#3
#4
for m in p.finditer('one1two2three3four4', 0, 10):
print(m.group())
#1
#2
for m in re.finditer(p, 'one1two2three3four4'):
print(m.group())
#1
#2
#3
#4
#-------------------- sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]) -----------------
"""
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换。
"""
p = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!'
m = re.search(p, s)
print(p.sub(r'\2 \1', s))
#say i, world hello!
def func(x):
return x.group(1).title() + ' ' + x.group(2).title()
print(p.sub(func, s))
#I Say, Hello World!
#-------------------- subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]) -----------------
"""
subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):
返回 (sub(repl, string[, count]), 替换次数)
"""
p = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!'
m = re.search(p, s)
print(p.subn(r'\2 \1', s))
#('say i, world hello!', 2)
def func(x):
return x.group(1).title() + ' ' + x.group(2).title()
print(p.subn(func, s))
#('I Say, Hello World!', 2)
在网上查阅引用了一些资料,顺带着的练习与总结,新手上路,不足之处多多指正