Python:正则表达式

正则表达式

一、简介:
正则表达式:是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现,需要在文件最开始的地方用import re来引入。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎-执行。


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


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


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

 

 示例:

>>> re.findall(r"a(\d+)b","a23b")
        ['23']
>>> re.findall(r"a(\d+?)b","a23b") 
        ['23']

 [ ]:

元字符[]表示字符类,在一个字符类中,只有字符^、-、]和\有特殊含义。
字符\仍然表示转义,字符-可以定义字符范围,字符^放在前面,表示非,取反。

>>> re.findall(r"a[bc]d","wwwwabcd")
[]
>>> re.findall(r"a[bcd]e","wwwwabcde")
[]
>>> re.findall(r"a[bcd]e","wwwwade")
['ade']
>>> re.findall(r"a[bc]d","wwwwabd")
['abd']
>>>
>>> re.findall(r"a[.]d","wwwwabd")
[]
>>> re.findall(r"a[.]d","wwwwa.d")
['a.d']
>>> re.findall(r"[a-z]","wwwwa.d")
['w', 'w', 'w', 'w', 'a', 'd']
>>> re.findall(r"[1-9]","ww3ww8a.d")
['3', '8']

 

 

 | :或    

 注:(?:a|b)使用方法

ret = re.findall('www.(baidu|laonanhai).com','sdad www.baidu.com')
print(ret)
#打印结果:['baidu']
ret = re.findall('www.(baidu|laonanhai).com','sdad www.laonanhai.com')
print(ret)
#打印结果:['laonanhai']
ret = re.findall('www.(?:baidu|laonanhai).com','sdad www.laonanhai.com')
print(ret)
#打印结果:['www.laonanhai.com']

 

 

 

[^]:取反

>>> re.findall(r"[^1-9]","ww3ww8a.d")
['w', 'w', 'w', 'w', 'a', '.', 'd']
>>> re.findall(r"[^1-9]","ww3ww8a.d0")
['w', 'w', 'w', 'w', 'a', '.', 'd', '0']

 

 

特殊符号:

”^“ “ $ ”分别指出一个字符串的开始和结束。

示例:

“^The”:表示以“The”开始的字符串

“ok$”:表示以“ok”结束的字符串

 

\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: 匹配一个单词边界,也就是指单词和空格间的位置。

\b只是匹配字符串开头结尾及空格回车等的位置, 不会匹配空格符本身 

示例:

\s,\w,\d:

>>> re.findall(r"\s","ww3w w8a.d0")
[' ']
>>> re.findall(r"\w","ww3ww8a.d0")
['w', 'w', '3', 'w', 'w', '8', 'a', 'd', '0']
>>> re.findall(r"\d","ww3ww8a.d0")
['3', '8', '0']

\b:

>>> re.findall(r"\babc\b","abcsdsadasabcasdsadasdabcasdsa")
[]
>>> re.findall(r"\babc","abc sdsadasabcasdsadasdabcasdsa")
['abc']
>>> re.findall(r"\babc\b"," abc sdsadasabcasdsadasdabcasdsa")
['abc']

 

 

 \:

反斜杠后边跟元字符去除特殊功能,
反斜杠后边跟普通字符实现特殊功能。
引用序号对应的字组所匹配的字符串。

>>> re.search(r"(alex)(eric)com\2","alexericcomeric").group()
'alexericcomeric'

 

三、函数:

匹配开头

match:re.match(pattern, string, flags=0)

>>> re.match('com', 'comwww.runcomoob').group()
'com'
>>> re.match('com', 'Comwww.runComoob',re.I).group()
'Com'

re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符

 

分组:

#无分组:
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("h\w+",origin)
print(r.group())
#打印结果:hello

#有分组:是将group中的值再匹配括号中的(从左到右,从外到里),有几个括号就取几个
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("(h)(\w+)",origin)
print(r.groups())
#打印结果:('h', 'ello')

#?P<>设置groupdict中的key
origin = "hello alex bcd alex lge alex acd 19"
r = re.match("(?P<k1>h)(?P<k2>\w+)",origin)
print(r.groupdict())
#打印结果:{'k1': 'h', 'k2': 'ello'}

 

 

 

匹配第一个

search(search有无分组情况和match一样):re.search(pattern, string, flags=0)

>>> re.search('\dcom', 'www.4comrunoob.5com').group()
'4com'

 

注意:
re.match('com', 'comwww.runcomoob')
re.search('\dcom', 'www.4comrunoob.5com')
一旦匹配成功,就是一个match object 对象,而match object 对象拥有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置


group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
1. group()返回re整体匹配的字符串,
2. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
3.groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。

 

>>> a = "123abc456"
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups() ('123', 'abc', '456')

 

group(0) 列出所有括号匹配部分,group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3)列出第三个括号匹配部分。
import re
>>> 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'

 

 

获取字符串中所有匹配项

findall:可以获取字符串中所有匹配的字符串,以列表形式返回所有匹配的字符串。

findall在有组的情况下,只匹配组里的情况,以列表形式返回。如果两个组分别匹配到组里的情况,就将作为一个元祖返回给列表。

import re
print(re.findall(r"a(\d+)b","a23b"))
#打印结果:['23']
print(re.search(r"a(\d+)b", "a23b").group())
#打印结果:a23b

 

>>> p = re.compile(r'\d+')
>>> print p.findall('one1two2three3four4')
['1', '2', '3', '4']
>>> re.findall(r'\d+','one1two2three3four4')
['1', '2', '3', '4']

 

 有无分组情况:

origin = "hello alex alex bcd abcd lge acd 19"
r = re.findall("a\w+",origin)
r1 = re.findall("(a\w+)",origin)
r2 = re.findall("(a)(\w+)",origin)
print(r)
print(r1)
print(r2)
#打印结果:
['alex', 'alex', 'abcd', 'acd']
['alex', 'alex', 'abcd', 'acd']
[('a', 'lex'), ('a', 'lex'), ('a', 'bcd'), ('a', 'cd')]


origin = "hello ax lex bed alex lge alex acd 19"
n = re.findall("(a)(\w)*" , origin)
print(n)
#打印结果:[('a', 'x'), ('a', 'x'), ('a', 'x'), ('a', 'd')]

 

*:0-多次,默认情况是贪婪的。有分组,取多次,默认取最后一个值,如果后面没有符合项,会匹配空

a = "alex"
n = re.findall("(\w)(\w)(\w)(\w)",a)
print(n)
n1 = re.findall("(\w)",a)
print(n1)
n2 = re.findall("(\w)*",a)
print(n2)
#打印结果:
[('a', 'l', 'e', 'x')]
['a', 'l', 'e', 'x']
['x', '']

n = re.findall("(\dasd)","lasd2asdp3asd98kif")
print(n)
#打印结果:['2asd', '3asd']
n = re.findall("(\dasd)*","lasd2asdp3asd98kif")
print(n)
#打印结果:['', '', '', '', '2asd', '', '3asd', '', '', '', '', '', '']

 

 

空格匹配:如果没有匹配到空格,将返回空内容,并且会返回自身

#1、匹配到符合项之后再从符合项之后开始匹配
n = re.findall("\d+\w\d+","a2b3c4d5")
print(n)
#打印结果:['2b3', '4d5']

#2、空格匹配(字符串中有八个字符,返回了九个空格)
n = re.findall("","a2b3c4d5")
print(n)
#打印结果:['', '', '', '', '', '', '', '', '']

 

 

re.compile(strPattern[, flag]):

>>> text = "JGood is a handsome boy, he is cool, clever, and so on..."
>>> regex = re.compile(r'\w*oo\w*')
>>> print regex.findall(text)
['JGood', 'cool']

 

 

sub :替换

re.sub(pattern, repl, string, max=0)

>>> re.sub("g.t","have",'I get A,  I got B ,I gut C')
'I have A,  I have B ,I have 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'

subn:返回替换次数

>>> re.subn("g.t","have",'I get A,  I got B ,I gut C')
('I have A,  I have B ,I have C', 3)

 

 

split:分割

>>> p = re.compile(r'\d+')
>>> p.split('one1two2three3four4')
['one', 'two', 'three', 'four', '']
>>> re.split('\d+','one1two2three3four4five')
['one', 'two', 'three', 'four', 'five']

 有无分组情况:

#无分组:
origin = "hello alex bcd abcd lge acd 19"
n = re.split("a\w+",origin)
print(n)
#打印结果:['hello ', ' bcd ', ' lge ', ' 19']

#有分组:
n = re.split("a(\w+)",origin)
print(n)
#打印结果:['hello ', 'lex', ' bcd ', 'bcd', ' lge ', 'cd', ' 19']

#添加参数2:2是最大分割次数
n = re.split("a(\w+)",origin,2)
print(n)
#打印结果:['hello ', 'lex', ' bcd ', 'bcd', ' lge acd 19']

 

 

 

finditer:finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]): 

搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。

>>> p = re.compile(r'\d+')
>>> iterator = p.finditer('12 drumm44ers drumming, 11 ... 10 ...')
>>> for match in iterator:
...  match.group() , match.span()
...
('12', (0, 2))
('44', (8, 10))
('11', (24, 26))
('10', (31, 33))

 

w = re.finditer(r'\d+','12drumm44ers drumming, 11...10...')
for aa in w:
    print(aa.group())
#打印结果:
12
44
11
10

 

练习:计算器计算:

1 - 2 * ( (60 - 30 + (-40.0/5) * (9 - 2 * 5/3 + 7 / 3 * 10/4*2 +10 *5/14)) -(-4*3)/(16-3*2))
 1 import re
 2 
 3 
 4 def add_op(arg):  # 定义加法函数
 5     arg = arg.replace("++", "+").replace("--", "+").replace("+-", "-").replace("-+", "-")  # 替换符号
 6     num = re.findall("([+\-]?\d+\.?\d*)", arg)  #匹配所有数字
 7     result = 0
 8     for i in num:   #循环数字列表进行累加
 9         result = result + float(i)
10     return result
11 
12 def mul(arg):   #定义乘除函数
13     while True:
14         result = re.split("(\d+\.?\d*[\*/][\+-]?\d+\.?\d*)",arg,1) #匹配乘法或除法
15         if len(result) == 3:
16             bef,cen,aft = result
17             if "*" in cen:  #判断乘号是否在cen里面
18                 num1,num2 = cen.split("*")  #将乘号进行分割得到乘数
19                 new_cen = float(num1) * float(num2)     #将乘数相乘得到乘积
20                 arg = bef +str(new_cen) + aft   #将乘积放入新的字符串表达式
21             elif "/" in cen:    #判断除号是否在cen里面
22                 num1,num2 = cen.split("/")  #分割除号得到除数和被除数
23                 new_cen = float(num1) / float(num2)     #进行除法运算
24                 arg = bef + str(new_cen) + aft      #将商放入新的字符串表达式
25         else:
26             return add_op(arg)
27 
28 def calc(arg):
29     while True:
30         arg = arg.replace(" ","")
31         result = re.split("\(([^()]+)\)",arg,1)     #匹配最里面的括号并且只取括号中的内容
32         if len(result) == 3:
33             bef,cen,aft = result
34             # 计算括号中的表达式,先乘除后加减,得到计算结果
35             r = mul(cen)
36             #使用计算结果组成新的字符串表达式
37             arg = bef + str(r) + aft
38         else:   #计算完括号后开始按照先乘除再加减的运算
39             return mul(arg)
40 
41 origin = "1 - 2 * ( (60 - 30 + (-40.0/5) * (9 - 2 * 5/3 + 7 / 3 * 10/4*2 +10 *5/14)) -(-4*3)/(16-3*2))"
42 r = calc(origin)
43 print(r)
44 print(eval(origin))

 

posted @ 2016-05-16 15:04  阿肉  阅读(221)  评论(0编辑  收藏  举报