python正则式

正则式是一个强大的东西,一定要好好深入一下。但在深入之前先玩点基本的吧

http://www.runoob.com/python/python-reg-expressions.html
http://blog.csdn.net/vah101/article/details/6170404

import re
# ======
# serach 和 match
# ======
# serach 和 match 返回的要么是None,要么是 match object
# search是搜索整个字符串, 返回**一个**满足的匹配;而match则是从字符串的**起始位置**开始匹配,类似于检测字符串是否满足模式,也就是第一个字符必须满足匹配。他们无法返回多行的多个匹配
# re.match(r'456','123456') 返回None
# re.match(r'(?<=123)456','123456') 返回None
# 下面是match object的dir
# ['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']
mathObj = re.search(r'/user/uid/(\d+)','http://qiuboai.com/user/uid/123')

# ======
# group
# ======
# group返回指定的分组,0返回完整匹配
mathObj.group(0) # 完整的匹配
mathObj.group(1) # 第1个分组
mathObj.group(N) # 第N个分组

# 因为实现了__getitem__,所以可以索引式访问,等同group[N]
mathObj[1] # 第1个分组

# 除了使用默认的数字组名外,还可以指定组名
m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
m.group('first_name')
# 'Malcolm'
m.group('last_name')
# 'Reynolds'

# ======
# groups
# ======
# groups返回包含所有分组的匹配结果的tuple,它接受一个参数作为未命中的默认值,整个值默认是None
mathObj.groups() # 返回一个tuple('1',)
m = re.match(r"(\d+)\.(\d+)", "24.1632")
m.groups()
# ('24', '1632')
m = re.match(r"(\d+)\.?(\d+)?", "24")
m.groups('XXX')
# ('24', 'XXX') #第二个分组未命中所以显示为xxx


# ======
# sub - 返回替换后的字符串
# subn - 返回一个tuple: 替换后的字符串, 匹配的数量
# ======
# 替换匹配的字符串,replace的赶脚
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import re

phone = "2004-959-559 # 这是一个国外电话号码"

# 删除字符串中的 Python注释 
num = re.sub(r'#.*$', "", phone)
print "电话号码是: ", num

# 删除非数字(-)的字符串 
num = re.sub(r'\D', "", phone)
print "电话号码是 : ", num

# 电话号码是:  2004-959-559 
#电话号码是 :  2004959559

正则表达式难点

(?:)    - 匹配但是不保存结果到$#
(?=)    - 肯定正环视,匹配的位置右边满足表达式
(?!)    - 否定正环视,匹配的位置右边不满足表达式
(?<=)   - 肯定逆环视,匹配的位置左边满足表达式
(?<!)   - 否定逆环视,匹配的位置左边不满足表达式
[A-Za-z0-9] - 列表
[^abcd] - 排除列表
(ab|12) - 可选序列
/^      - 开始位置
$/      - 结束位置  

学以致用

学习正则的目的就是为了

  1. 截取匹配的字符串 - match, search, group[N], findall, finditer
  2. 替换匹配的字符串 - re.sub(), repl.subn()

比较复杂的多行匹配:
多行可以split为多个单行串,处理完后再合并,也可以直接处理,注意的是:需要配置re.S|re.M

import re

s = '''
def post(self):
    form = self.Form(**self.POST)  
    model = Driver(**form.data)
    self.db.add(model)
    self.db.commit()
    return JsonResponse(self, '50000', data=model.json)

def space(n):
    return ''.join([' ' for x in range(n)])    
'''

# 1. 最简单的方式
# s1 = '\n    '.join(s.splitlines())
# print(s1)

# 一次匹配多个结果,最终还是要逐个处理
r = re.finditer(r'^.*$', s, re.M)
for x in r:
    print('    '+x.group(0))

# search只能拿到第一个匹配结果,所以还是要split成多行后处理
r = re.search(r'(^.*$)', s, re.S | re.M)
print(r.group(0))
print(r.groups())

serach

b = '''a23b
a34b'''
r = re.findall(r'^a(\d+)b$', b, re.M)
print(r) # ['23', '34'] 所有结果
r = re.search(r'^a(\d+)b$', b, re.M)
print(r) # <_sre.SRE_Match object; span=(0, 4), match='a23b'> 只有一个结果

findall

import re
s = '<strong><i>Mark</i></strong> <strong><i>Wan</i></strong>'

# 不指定分组默认匹配分组0
r = re.findall(r'strong><i>\w*</i></strong>', s)
print(r)
# ['strong><i>Mark</i></strong>', 'strong><i>Wan</i></strong>']

# 指定分组后匹配每个分组
r = re.findall(r'(<strong><i>)(\w*)(</i></strong>)', s)
print(r)
# [('<strong><i>', 'Mark', '</i></strong>'), ('<strong><i>', 'Wan', '</i></strong>')]

# 使用环视, 惰性模式
r = re.findall(r'(?<=<strong><i>).*?(?=</i></strong>)', s)
print(r)
# ['Mark', 'Wan']

# 只分组需要返回的部分
r = re.findall(r'<strong><i>(\w*)</i></strong>', s)
print(r)
# ['Mark', 'Wan']
posted @ 2017-04-22 10:55  CooMark  阅读(280)  评论(0编辑  收藏  举报