re模块
re.sub
Python 的re模块提供了re.sub用于替换字符串中的匹配项。
语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
- flags : 编译时用的匹配模式,数字形式。
实例
#!/usr/bin/python3
import re
phone = "2004-959-559 # 这是一个电话号码"
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)
结果
电话号码 : 2004-959-559
电话号码 : 2004959559
zip()函数
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
zip([iterable, ...])
# iterabl -- 一个或多个迭代器;
isinstance()
判断一个对象是否是一个已知的类型
isinstance(object, type)
>>> a = 5
>>> b = 'b'
>>> c = [1,2,3]
>>> d = {'d': 1}
>>>
>>> isinstance(a, int)
True
>>> isinstance(a, list)
False
>>> isinstance(b, str)
True
>>> isinstance(b, int)
False
>>> isinstance(c, list)
True
>>> isinstance(d, dict)
True
map,el表达式
list(map(lambda el: self.label_map_reverse[el], src))
例子:
from functools import reduce
l = ['a', 'bc', 'cde', 'defg']
lf = filter(lambda x: len(x) > 2, l)
lm = map(lambda x: x+'_n', l)
lr = reduce(lambda x,y: x+y, l)
print(list(lf))
print(list(lm))
print(lr)
输出:
['cde', 'defg']
['a_n', 'bc_n', 'cde_n', 'defg_n']
abccdedefg
map 函数:
map(function, iterable, ...)
- function – 函数
- iterable – 一个或多个序列
>>>def square(x) : # 计算平方数
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
max()
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
reg = re.compile('a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*')
#返回一个字符串里按字母表排序的最长子字符串
def longest(s):
print reg.findall(s)
#['abcde', 'ap', 'bcdef', '']
return max(reg.findall(s), key=len)
#加或不加效果相同
print longest('abcdeapbcdef')
Python内置函数max()、min()和sorted()以及列表方法sort()都有一个参数key用来指定排序规则,解决的就是这个问题。
key参数应该是一个可调用对象,在Python中,类、自定义函数、内置函数、lambda表达式、带有特殊方法__call__()的对象都属于可调用函数。
\d
'00\d'
可以匹配'007'
,但无法匹配'00A'
;'\d\d\d'
可以匹配'010'
;'\w\w\d'
可以匹配'py3'
;
匹配任意字符串
'py.'
可以匹配'pyc'
、'pyo'
、'py!'
等等。
要匹配变长的字符,在正则表达式中,用*
表示任意个字符(包括0个),用+
表示至少一个字符,用?
表示0个或1个字符,用{n}
表示n个字符,用{n,m}
表示n-m个字符:
\s
\d{3}\s+\d{3,8}
。
我们来从左到右解读一下:
\d{3}
表示匹配3个数字,例如'010'
;\s
可以匹配一个空格(也包括Tab等空白符),所以\s+
表示至少有一个空格,例如匹配' '
,' '
等;\d{3,8}
表示3-8个数字,例如'1234567'
。
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。
进阶
要做更精确地匹配,可以用[]
表示范围,比如:
[0-9a-zA-Z\_]
可以匹配一个数字、字母或者下划线;[0-9a-zA-Z\_]+
可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100'
,'0_Z'
,'Py3000'
等等;[a-zA-Z\_][0-9a-zA-Z\_]*
可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;[a-zA-Z\_][0-9a-zA-Z\_]{0, 19}
更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B
可以匹配A或B,所以(P|p)ython
可以匹配'Python'
或者'python'
。
^
表示行的开头,^\d
表示必须以数字开头。
$
表示行的结束,\d$
表示必须以数字结束。
你可能注意到了,py
也可以匹配'python'
,但是加上^py$
就变成了整行匹配,就只能匹配'py'
了。
分组
- 提取子串
- 用
()
表示的就是要提取的分组(Group)
^(\d{3})-(\d{3,8})$
分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码
>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
>>> m
<_sre.SRE_Match object at 0x1026fb3e8>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'
match()和search()区别
match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none
- match()从开头开始匹配
详见参考网址
案例
import re
# 正则匹配
def find_text(text):
word_dic = {}
# m = re.match(u'<ESSAY title')
reg = re.compile('<ESSAY title')
# print(re.findall(u"<ESSAY title=\"(.+?)\">", text))
sen_list = []
for i in range(len(text)):
if text[i].startswith("<PASSAGE"):
sen_list.append(text[i][24:-11])
elif text[i].startswith("<WRONG>") and text[i+1].startswith("<CORRECTION>"):
word_dic[text[i][7:-9]] = text[i+1][12:-14]
# print(sen_list)
# print(word_dic)
return sen_list, word_dic