【笔记】Python基础七:正则表达式re模块

时间:2021-07-05 22:40:42

一,介绍

正则表达式(RE)是一种小型的,高度专业化的编程语言,在python中它内嵌在python中,并通过re模块实现。正则表达式模式被编译成一系列的字节码,然后由C编写的匹配引擎执行。

 字符匹配(普通字符,元字符):

1 普通字符:大多数字符和字母都会和自身匹配
              >>> re.findall('alex','yuanaleSxalexwupeiqi')
                      ['alex'] 

2 元字符:. ^ $ * + ? { } [ ] | ( ) \

 二,元字符

(一)点.通配符,代替除了换行符\n以外的任意一个字符

>>> import re
>>> re.findall("alex","sdffalexjj")
['alex']
>>> re.findall("a..x","sdffalexjj")
['alex']
>>> re.findall("a...x","sdffalexjj")
[]

(二)尖角号^,表示以后面的字符串开头;$符,表示以前面的字符串结尾。

>>> re.findall("^a..x","asdffalexjj")
[]
>>> re.findall("^a..x","asdxfalexjj")
['asdx']
>>> re.findall("a..x$","asdxfa22x")
['a22x']

(三)重复符号,* + ? { }

1,*是重复紧挨着的字符,从0次到无穷次

>>> re.findall("alex*","asdxfale")
['ale']

2,+是1到无穷次,如果没有(0次)就匹配不上

>>> re.findall("alex+","asdxfale")
[]
>>> re.findall("alex+","asdxfalexxx")
['alexxx']

3,?是0或者1次

>>> re.findall("alex?","asdxfalexxx")
['alex']
>>> re.findall("alex?","asdxfale")
['ale']

4,{}自定义范围   {0,}==*   {1,}==+   {0,1}==?  {6}==重复6次  {1,6}重复1到6次

>>> re.findall("alex{6}","asdxfalexxxxxx")
['alexxxxxx']
>>> re.findall("alex{6}","asdxfalex")
[]
>>> re.findall("alex{0,1}","asdxfalex")
['alex']
>>> re.findall("alex{0,1}","asdxfale")
['ale']

注意*,+,?等都是贪婪匹配,后面加?号使其变成惰性匹配

>>> re.findall('abc*?','abcccccc')
['ab']
>>> re.findall('abc*','abcccccc')
['abcccccc']
>>> re.findall('abc+?','abcccccc')
['abc']

(四)字符集[]

实现或的逻辑

>>> re.findall('x[yz]','xyuuxzuu')
['xy', 'xz']
>>> re.findall('x[yz]p','xypuuxzuu')
['xyp']
>>> re.findall('x[y,z]p','xypuuxzuux,p')
['xyp', 'x,p']

 []内只有三个字符例外

1,-表示范围

>>> re.findall('x[a-z]','xypuuxzuux,p')
['xy', 'xz']
>>> re.findall('x[a-z]*','xypuuxzuux')
['xypuuxzuux']
>>> re.findall('x[a-z]*','xypuuxzuux9n')
['xypuuxzuux']

2,^非

>>> re.findall('x[^a-z]','x12')
['x1']
>>> re.findall('x[^a-z]','xy')
[]
>>> re.findall("\([^()]*\)","12+(34*6+2-5*(2-1))")
['(2-1)']

 3,\  后面跟元字符去除特殊功能,比如\.

          后面跟普通字符实现特殊功能,比如\d

\d  匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b  匹配一个特殊字符边界,比如空格 ,&,#等

>>> re.findall("\d","12+(34*6+2-5*(2-1))")
['1', '2', '3', '4', '6', '2', '5', '2', '1']
>>> re.findall("\d+","12+(34*6+2-5*(2-1))")
['12', '34', '6', '2', '5', '2', '1']
>>> re.findall("[0-9]+","12+(34*6+2-5*(2-1))")
['12', '34', '6', '2', '5', '2', '1']
>>> re.findall("\D+","12+(34*6+2-5*(2-1))")
['+(', '*', '+', '-', '*(', '-', '))']
>>> re.findall("\D+","hello world")
['hello world']
>>> re.findall("\s+","hello world")
[' ']
>>> re.findall("\S+","hello world")
['hello', 'world']
>>> re.findall("\w+","hello_world")
['hello_world']
>>> re.findall("\W+","~!@#$%^&*()")
['~!@#$%^&*()']
>>> re.findall("www\.baidu","www.baidu")
['www.baidu']

 \b的用法讨论。re.findall("I\b","I am ooo"),这里面python解释器会识别出\b,并处理后交给re模块,re模块收到的不再是\b,于是产生问题。

解决方法1:使用r(raw string原生字符串)re.findall(r"I\b","I am ooo")

解决方法2:使用\\,由python解释器处理一次,去掉一个\,传给re模块就变成\b,re.findall("I\\b","I am ooo")

                    举例:找出"c\l",反推re模块接收为"c\\l",反推python解释器接收为"c\\\\l",最后re.findall("c\\\\l","I am oc\lo")   

>>> re.findall("c\\\\l","I am oc\lo")
['c\\l']

 (五)管道符|

|之前是一部分,|之后是一部分,两者是或的关系

>>> re.findall("ka|b","I am ka|b")
['ka', 'b']

(六)分组介绍

1,匿名分组使用()

>>> re.findall("(abc)+","I am abcd")
['abc']

注意:如果使用()分组,findall会优先显示匹配到的分组()里面的内容,而不是匹配的全部内容

           如果就想要www.baidu.com完整匹配,需要在括号里加入?:

>>> re.findall("www\.(baidu|163)\.com","dfsgfwww.baidu.com112")
['baidu']
>>> re.findall("www\.(?:baidu|163)\.com","dfsgfwww.baidu.com112")
['www.baidu.com']

  利用“优先显示匹配到的结果”解释下面的的现象

>>> re.findall("(abc)+","I am abcabcabc")
['abc']

  上面实际把abc作为一个整体匹配,匹配到1次,结果是abcabcabc,但是只显示1个abc。如果想要全部显示,则需要使用上面的?:,如下:

>>> re.findall("(?:abc)+","I am abcabcabc")
['abcabcabc']

  这种整体分组使用括号()匹配和单个字符匹配abc+是不一样的,如下abc+匹配到了3次而不是像上面分组的1次

>>> re.findall("abc+","I am abcabcabc")
['abc', 'abc', 'abc']

  同理,分组的匹配出现多次的情况:

>>> re.findall("(abc)+","I am abcabc111abc")
['abc', 'abc']

 

2,命名分组:?P<name>对匹配没有任何影响,只是起了一个分组的名字叫name,而name作为group方法调用的参数。实际对匹配起作用的仍然是[a-z]+)\d+

>>> re.search("(?P<name>[a-z]+)\d+","alex36wusir34xialv33").group()
'alex36'
>>> re.search("(?P<name>[a-z]+)\d+","alex36wusir34xialv33").group("name")
'alex'
>>> re.search("(?P<name>[a-z]+)(?P<age>\d+)","alex36wusir34xialv33").group("age")
'36'

 

三,方法

1,findall,返回所有满足匹配条件的结果,放在列表里

2,serach,在字符串内查找模式匹配,找到第一个然后返回一个对象。通过调用group()方法得到匹配的字符串,如果字符串没有匹配返回None

3,match,只会在开始处进行匹配

>>> re.match("(\d+)","alex36wusir34xialv33")
>>> re.match("(\d+)","56alex36wusir34xialv33")
<_sre.SRE_Match object; span=(0, 2), match='56'>
>>> re.match("(\d+)","56alex36wusir34xialv33").group()
'56'

4,split,分割函数

>>> re.split("[ |]","hello abc|def")
['hello', 'abc', 'def']
>>> re.split("[ab]","asdabcd")
['', 'sd', '', 'cd']
>>> re.split("[ab]","abc")
['', '', 'c']

5,sub,替换函数,4个参数:1:模式,2:替换为字符,3:搜索字符串,4:替换次数

>>> re.sub("\d+","A","J12abc234ffg55")
'JAabcAffgA'
>>> re.sub("\d","A","J12abc234ffg55")
'JAAabcAAAffgAA'
>>> re.sub("\d","A","J12abc234ffg55",4)
'JAAabcAA4ffg55'
>>> re.subn("\d","A","J12abc234ffg55")
('JAAabcAAAffgAA', 7)

6,compile,模式先编译好,以后就可以直接调用。好处是写一次可以使用多次提高效率。

>>> com=re.compile("\d+")
>>> com.findall("fjlkdad234hfjksd3421")
['234', '3421']
>>> com.findall("444adf555")
['444', '555']

7,finditer,返回的是迭代器对象,不再是列表。好处和迭代器是一样的。

>>> ret=re.finditer("\d","sdfds123fr")
>>> next(ret).group()
'1'
>>> next(ret).group()
'2'

 

 

 

参考:http://www.cnblogs.com/yuanchenqi/articles/5732581.html