正则表达式
正则表达式内部函数详解http://www.runoob.com/python/python-reg-expressions.html
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
本章节主要介绍Python中常用的正则表达式处理函数。
>>> "abcde".find("b") 1 >>> "abcde".find("bc") 1 >>> "abcde".split("b") ['a', 'cde'] >>> "abcd".replace("ab","ee") 'eecd' >>>
字符匹配(普通字符,元字符):
普通字符:
大多数字符和字母都会和自身匹配
>>> re.findall("alex","yuanaleSxalexwupeiqi") ['alex'] >>> re.findall("alex","yuanaleSxalewxwupeiqi") [] >>> re.findall("alex","yuanaleSxalexwupeiqialex") ['alex', 'alex']
元字符
):. ^ $ * + ? {} [] | ()
. :匹配一个除了换行符任意一个字符
>>> re.findall("alex.w","aaaalexaw") ['alexaw']
#一个点只能匹配一个字符
^ :只有后面跟的字符串在开头,才能匹配上
>>> re.findall("alex.w","aaaalexaw") ['alexaw']
#"^"这个符号控制开头,所以写在开头
$ :只有它前面的字符串在检测的字符串的最后,才能匹配上
>>> re.findall("alex$","alexyuanaleSxalexwupeiqi") [] >>> re.findall("alex$","alexyuanaleSxalexwupeiqialex") ['alex']
* :它控制它前面那个字符,他前面那个字符出现0到多个都可以匹配上
>>> re.findall("alex*","aaaale") ['ale'] >>> re.findall("alex*","aaaalex") ['alex'] >>> re.findall("alex*","aaaalexxxxxxxxx") ['alexxxxxxxxx'] #如果想控制多个字符就把那几个字符用括号括起来???? >>> re.findall("(alex)*","aaaalexexexex") ['', '', '', 'alex', '', '', '', '', '', '', '']
+ :匹配前面那个字符1到多次
>>> re.findall("alex+","aaaalexxxxxxxxx") ['alexxxxxxxxx'] >>> re.findall("alex+","aaaalex") ['alex'] >>> re.findall("alex+","aaaale") []
? :匹配前面那个字符0到1个,多余的只匹配一个
>>> re.findall("alex?","aaaale") ['ale'] >>> re.findall("alex?","aaaalex") ['alex'] >>> re.findall("alex?","aaaalexxxxxx") ['alex']
{} :控制匹配个数,可以有区间(闭区间)
>>> re.findall("alex{3}","aaaalexxxxxx") ['alexxx'] >>> re.findall("alex{3}","aaaalexx") [] >>> re.findall("alex{3}","aaaale") [] >>> re.findall("alex{3}","aaaalexxx") ['alexxx'] >>> re.findall("alex{3,5}","aaaalexxxxxxxxx") ['alexxxxx'] >>> re.findall("alex{3,5}","aaaalexxx") ['alexxx'] >>> re.findall("alex{3,5}","aaaalexx") []
[] :控制匹配字符,[bc]意思是这个地方可以是b,也可以是c,但不能是bc因为是
b或c >>> re.findall("a[bc]d","aaaabd") ['abd'] >>> re.findall("a[bc]d","aaaacd") ['acd'] >>> re.findall("a[bc]d","aaaabcd") []
:
后面跟元字符去除特殊功能,
后面跟普通字符实现特殊功能。
引用序号对应的字组所匹配的字符串 (一个括号为一个组)
#2 就相当于eric 第二个组
>>> re.search(r"(alex)(eric)com2","alexericcomeric").group() 'alexericcomeric' >>> re.search(r"(alex)(eric)com1","alexericcomalex").group() 'alexericcomalex' >>> re.search(r"(alex)(eric)com12","alexericcomalexeric").group() 'alexericcomalexeric'
d :匹配任何十进制数;它相当于类[0-9]
>>> re.findall("d","aaazz1111344444c") ['1', '1', '1', '1', '3', '4', '4', '4', '4', '4'] >>> re.findall("dd","aaazz1111344444c") ['11', '11', '34', '44', '44'] >>> re.findall("d0","aaazz1111344444c") [] >>> re.findall("d3","aaazz1111344444c") ['13'] >>> re.findall("d4","aaazz1111344444c") ['34', '44', '44']
D :匹配任何非数字字符;它相当于类[^0-9]
>>> re.findall("D","aaazz1111344444c") ['a', 'a', 'a', 'z', 'z', 'c'] >>> re.findall("DD","aaazz1111344444c") ['aa', 'az'] >>> re.findall("DdD","aaazz1111344444c") [] >>> re.findall("DdD","aaazz1z111344444c") ['z1z']
s :匹配任何空白字符;它相当于类[
fv]
>>> re.findall("s","aazz1 z11..34c") [' ']
S :匹配任何非空白字符;它相当于类[^
fv]
w :匹配任何字母数字字符;他相当于类[a-zA-Z0-9_]
>>> re.findall("w","aazz1z11..34c") ['a', 'a', 'z', 'z', '1', 'z', '1', '1', '3', '4', 'c']
W :匹配任何非字母数字字符;它相当于类[^a-zA-Z0-9_]
:匹配一个单词边界,也就是指单词和空格间的位置
>>> re.findall(r"abc","abc sdsadasabcasdsadasdabcasdsa") ['abc'] >>> re.findall(r"alex","abc alex abcasdsadasdabcasdsa") ['alex'] >>> >>> re.findall("\balex\b","abc alex abcasdsadasdabcasdsa") ['alex'] >>> re.findall("alex","abc alex abcasdsadasdabcasdsa") []
() :把括号内字符作为一个整体去处理
>>> re.search(r"a(d+)","a222bz1144c").group() 'a222' >>> re.findall("(ab)*","aabz1144c") ['', 'ab', '', '', '', '', '', '', ''] #??? >>> re.search(r"a(d+)","a222bz1144c").group() 'a222' >>> re.search(r"a(d+?)","a222bz1144c").group() +的最小次数为1 'a2' >>> re.search(r"a(d*?)","a222bz1144c").group() *的最小次数为0 'a'
#非贪婪匹配模式 加? ,但是如果后面还有匹配字符,就无法实现非贪婪匹配
#(如果前后均有匹配条件,则无法实现非贪婪模式
>>> re.findall(r"a(d+?)b","aa2017666bz1144c") ['2017666'] >>> re.search(r"a(d*?)b","a222bz1144c").group() 'a222b' >>> re.search(r"a(d+?)b","a277722bz1144c").group() 'a277722b'
元字符在字符集里就代表字符,没有特殊意义(有几个例外)
>>> re.findall("a[.]d","aaaacd") [] >>> re.findall("a[.]d","aaaa.d") ['a.d']
例外
[-] [^] []
[-]
#匹配单个字符,a到z所有的字符
>>> re.findall("[a-z]","aaaa.d") ['a', 'a', 'a', 'a', 'd'] >>> re.findall("[a-z]","aaazzzzzaaccc") ['a', 'a', 'a', 'z', 'z', 'z', 'z', 'z', 'a', 'a', 'c', 'c', 'c'] >>> >>> re.findall("[1-3]","aaazz1111344444c") ['1', '1', '1', '1', '3']
[^]
#匹配除了这个范围里的字符,(^在这里有 非 的意思)
>>> re.findall("[^1-3]","aaazz1111344444c") ['a', 'a', 'a', 'z', 'z', '4', '4', '4', '4', '4', 'c'] >>> re.findall("[^1-4]","aaazz1111344444c") ['a', 'a', 'a', 'z', 'z', 'c']
[]
>>> re.findall("[d]","aazz1144c") ['1', '1', '4', '4']
flags 编译标志位
re.I 使匹配对大小写不敏感
>>> re.search("com","COM").group() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'group' >>> re.search("com","COM",re.I).group() 'COM'
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响^和$
re.S 使.匹配包括换行在内的所有字符
>>> re.findall(".","abc de") ['a', 'b', 'c', 'd', 'e'] >>> re.findall(".","abc de",re.S) ['a', 'b', 'c', ' ', 'd', 'e']
re.U 根据Unicode字符集解析字符。这个标志影响 w, W, , B
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
match: re.match(pattern,string,flags=0)
flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区别大小写
re.match("com","comwww.runcomoob").group() re.match("com","Comwww.runComoob",re.I).group() search:re.search(pattern,string,flags=0) re.search("dcom","www.4comrunoob.5com").group()
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
而re.search匹配整个字符串,直到找到一个匹配。
match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
group() 返回被RE匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配(开始,结束)的位置
group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串,获取匹配到的所有结果(无论是否有组)
a. group ()返回re整体匹配的字符串,
b. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
c. groups ()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。
a = "123abc456" re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体 re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123 re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456
sub subn:
re.sub(pattern, repl, string, max=0)
>>> re.sub("g.t","have","I get A, I got B, I gut C")#匹配g.t字符,用have替换(.匹配一个除了换行符任意一个字符) 'I have A, I have B, I have C' >>> re.sub("got","have","I get A, I got B, I gut C") 'I get A, I have B, I gut C' >>> re.sub("g.t","have","I get A, I got B, I gut C",2)#替换两个 'I have A, I have B, I gut C' >>> re.sub("g.t","have","I get A, I got B, I gut C",1) 'I have A, I got B, I gut C' >>> re.subn("g.t","have","I get A, I got B, I gut C")#使用re.subn显示替换里多少个 ('I have A, I have B, I have C', 3)
re.compile(strPattern[, flag]):
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。 第二个参数flag是
匹配模式,取值可以使用按位或运算符‘|‘表示同时生效,比如re.I | re.M可以把正则表达式编译成一个正
则表达式对象。可以把那些经常使用的正则表达式编译成正则表达式对象,这样可以提高一定的效率。下面是
一个正则表达式对象的一个例子:
>>> text = "JGood is a handsome boy, he is cool, clever, and so on..." >>> regex = re.compile(r"w*oow*") >>> print regex.findall(text) ['JGood', 'cool']
split:
p = re.compile(r"d+") #+:匹配前面那个字符1到多次 p.split("one1two2three3four4") #spilt分割 >>> p = re.compile(r"d+") >>> p.split("one1two2three3four4") ['one', 'two', 'three', 'four', ''] re.split("d+","one1two2three3four4") >>> re.split("d+","one1two2three3four4") ['one', 'two', 'three', 'four', ''] >>> re.split("d+","4one1two2three3four4") ['', 'one', 'two', 'three', 'four', '']#如果分割时左边或者右边已经被分过 >>> re.split("[bc]","abcd")#或者是无字符的情况下,就分出一个空字符 ['a', '', 'd']
finditer():
>>> p = re.compile(r"d+") >>> iterator = p.finditer("12 drumm44ers drumming, 11 ... 10 ...") >>> >>> iterator <callable-iterator object at 0x02626990> >>> for match in iterator: ... match.group() , match.span()#每个数字以及它们出现的位置 ...
('12', (0, 2))
('44', (8, 10))
('11', (24, 26))
('10', (31, 33))
re.findall("","abccom")
#要想匹配出\,因为本来就有特殊意义,所以需要转意一下,\,而只转一下仅仅是在python下转意了 ,在正则表达式下
并没有转,所以在python下先转两个 \,然后到正则表达式下在输入一个就是转一个所以最后需要写四个
>>> re.findall("\\","abccom") ['\'] #匹配到两个,有一个是转意字符
如果不想要这么麻烦就需要调用原生字符串rawstring,使用时在前面加一个r
>>> re.findall(r"\","abccom") ['\']
由于我们是在python下使用的正则表达式,所以特殊字符需要多次转意,而使用了rawstring之后,就不用在多次转意
仅仅就使用正则的规则就可以
>>> re.findall(r"d","www4dd6") ['4', '6'] >>> re.findall("\d","www4dd6") ['4', '6'] >>> re.findall("d","www4dd6") ['4', '6']
#在这里d成功的原因是因为d在ascii码中没有特殊含义,所以在这里就自动转意了,不过正规的写法就是前两个
>>> re.findall(r"abc","abcsd abc") ['abc', 'abc'] >>> re.findall(r"abc","abcsd abc") ['abc'] >>> re.findall(r"abc","abcsd abc*") ['abc'] >>> re.findall(r"abc","*abcsd*abc") ['abc', 'abc']
#检测单词边界不一定就是空格,还可以是除了字母以外的特殊字符
>>> re.findall("www.(baidu|laonanhai).com","mdzz www.baidu.com") ['baidu']
#findall会优先显示组里的内容(优先捕获)
>>> re.findall("www.(?:baidu|laonanhai).com","mdzz www.baidu.com") ['www.baidu.com']
#在组里(括号里)加 ?: 就可以取消优先捕获