正则表达式
动机 :
1. 处理文本称为计算机主要工作之一
2. 根据文本内容进行固定搜索是文本处理的常见工作
3. 为了快速方便的处理上述问题,正则表达式技术诞生,逐渐发展为一个单独技术被众多语言使用
定义 :
即高级文本匹配模式,提供了搜索,替代等功能,本质是由一些字符和特殊符号组成的字串。这个字串描述了字符和字符的重复行为,可以匹配某一类特征的字符串集合。
目标 :
1.熟练正则表达式符号和用法
2.能够正确的理解和简单使用正则表达式进行匹配
3.能够使用python re模块操作正则表达式
正则特点:
* 方便进行检索和修改
* 支持语言众多
* 使用灵活变化多样
* 文本处理,mongo存储某一类型字串,django、tornado路由,爬虫文本匹配
正则的规则和用法
re.findall(regex,string)
功能 : 使用正则表达式匹配字符串
参数 : regex : 正则表达式
string : 目标字符串
返回值 : 匹配到的内容
一、元字符 (即正则表达式中有特殊含义的字符)
(1)普通字符
元字符 : abc
匹配规则 : 匹配相应的普通字符
findall:在字符串中查找所有匹配成功的组,返回匹配成功的结果列表
In [1]: import re
In [2]: re.findall('ab','abcdeabcde')
Out[2]: ['ab', 'ab']
(2)使用 或 多个正则同时匹配
元字符 : |
匹配规则:符号两侧的正则均能匹配
In [3]: re.findall('ab|fh','abacfhab')
Out[3]: ['ab', 'fh', 'ab']
In [4]: re.findall('ab | fh','abacfhab')
Out[4]: []
注:|符号两边不能有空格,有则匹配不了
(3)匹配单一字符
元字符 : .
匹配规则: 匹配任意一个字符 '\n'除外
In [5]: re.findall('f.o','affooasand f@o')
Out[5]: ['ffo', 'f@o']
(4)匹配字符串开头
元字符 : ^
匹配规则: 匹配一个字符串的开头位置
In [6]: re.findall('^hello','hello world')
Out[6]: ['hello']
(5)匹配字符串结尾
元字符: $
匹配规则: 匹配一个字符串的结尾位置
In [7]: re.findall('py$','hello.py')
Out[7]: ['py']
In [8]: re.findall('py$','python')
Out[8]: []
(6)匹配重复0次或多次
元字符: *
匹配规则:匹配前面出现的正则表达式 0次或者多次
In [9]: re.findall('ab*','abcdeabasdfabbbbb')
Out[9]: ['ab', 'ab', 'a', 'abbbbb']
In [10]: re.findall('.*py$','hello.py')
Out[10]: ['hello.py']
In [11]: re.findall('.*py','hello.pyc')
Out[11]: ['hello.py']
In [12]: re.findall('.*py$','hello.pyc')
Out[12]: []
(7)匹配重复1次或多次
元字符 : +
匹配规则: 匹配前面正则表达式至少一次
In [13]: re.findall('ab+','abcdeabasdfabbbbb')
Out[13]: ['ab', 'ab', 'abbbbb']
In [14]: re.findall('.+\.py$','a.py')
Out[14]: ['a.py']
(8)匹配重复0次或1次
元字符: ?
匹配规则 : 匹配前面出现的正则表达式0次或1次
In [15]: re.findall('ab?','abcdeabasdfabbbbb')
Out[15]: ['ab', 'ab', 'a', 'ab']
(9)匹配重复指定次数
元字符 : {N}
匹配规则 : 匹配前面的正则表达式N次
In [16]: re.findall('ab{3}','abcdeabasdfabbbbb')
Out[16]: ['abbb']
(10)匹配重复指定次数范围
元字符 : {M,N}
匹配规则 : 匹配前面的正则表达式 m次到n次
In [17]: re.findall('ab{2,5}','abbcdeabbbbasdfabbbbb')
Out[17]: ['abb', 'abbbb', 'abbbbb']
(11)字符集匹配
元字符 : [abcd]
匹配规则 : 匹配中括号中的字符集,或者是字符集区间 的一个字符
字符集不匹配
元字符 : [^ abc]
匹配规则 : 匹配出字符集中字符的任意一个字符
In [18]: re.findall('[^abce]','abcdefgh')
Out[18]: ['d', 'f', 'g', 'h']
In [19]: re.findall('[^_0-9a-zA-Z]','740536464@qq.com')
Out[19]: ['@', '.']
(12)匹配任意数字(非数字)字符
元字符 : \d [0-9] \D [^0-9]
匹配规则: \d 匹配任意一个数字字符 \D 匹配任意非数字字符
In [20]: re.findall('1\d{10}','15100317766')
Out[20]: ['15100317766']
(13)匹配任意普通字符(特殊字符)
元字符 : \w [_0-9a-zA-Z] \W [^_0-9a-zA-Z]
匹配规则 : \w 匹配数字字母下划线 \W 除了数字字母下划线
In [22]: re.findall('[A-Z]\w*','Hello World')
Out[22]: ['Hello', 'World']
In [23]: re.findall('\w*-\d*','wangming-56')
Out[23]: ['wangming-56']
(14)匹配任意 (非)空字符
元字符 : \s \S
匹配规则: \s 任意空字符 [ \n\0\t\r] 空格 换行 回车 制表
\S 任意非空字符
In [26]: re.findall('hello\s+\S+','hello lily hello lucy hellokad')
Out[26]: ['hello lily', 'hello lucy']
(15)匹配字符串开头结尾
元字符 : \A ^ \Z $
匹配规则: \A 表示匹配字符串开头位置
\Z 表示匹配字符串的结尾位置
In [27]: re.findall('\Aabc\Z','abc')
Out[27]: ['abc']
In [28]: re.findall('\Aabc\Z','abcabc')
Out[28]: []
(16)匹配(非)单词边界
元字符: \b \B
匹配规则 \b 匹配一个单词的边界
\B 匹配一个单词的非边界
数字字母下划线和其他字符的交界处认为是单词边界
In [29]: re.findall('is','This is a test')
Out[29]: ['is', 'is']
In [30]: re.findall(r'\bis\b','This is a test')
Out[30]: ['is']
二、贪婪和非贪婪
贪婪模式 : 在使用重复元字符的时候(* + ?{m,n}),元字符的匹配总是尽可能多的向后匹配更多内容,即为贪婪模式。贪婪模式是一种默认情况
In [31]: re.findall('ab*','abbbbalkdffab')
Out[31]: ['abbbb', 'a', 'ab']
In [32]: re.findall('ab+','abbbbalkdffab')
Out[32]: ['abbbb', 'ab']
In [33]: re.findall('ab?','abbbbalkdffab')
Out[33]: ['ab', 'a', 'ab']
In [34]: re.findall('ab{3,5}','abbbbalkdffab')
Out[34]: ['abbbb']
非贪婪模式 : 尽可能少的匹配内容,只要满足正则条件即可
In [35]: re.findall('ab{3,5}?','abbbbalkdffab')
Out[35]: ['abbb']
In [36]: re.findall('ab*?','abbbbalkdffab')
Out[36]: ['a', 'a', 'a']
In [37]: re.findall('ab+?','abbbbalkdffab')
Out[37]: ['ab', 'ab']
In [38]: re.findall('ab??','abbbbalkdffab')
Out[38]: ['a', 'a', 'a']
In [39]: re.findall('ab?','abbbbalkdffab')
Out[39]: ['ab', 'a', 'ab']
三、正则表达式的分组
使用()为正则表达式分组
((ab)cd(ef)) : 表示给ab分了一个子组
1. 正则表达式的子组用()表示,增加子组后对整体的匹配没有影响
2. 每个正则表达式可以有多个子组,子组由外到内由左到右为第一第二第三。。。。。。子组
3. 子组表示一个内部整体,很多函数可以单独提取子组的值
4. 子组可以改变 重复行为,将子组作为一个整体重复
match():尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
In [40]: re.match('abcdef','abcdefghigk').group()
Out[40]: 'abcdef'
In [41]: re.match('(ab)cdef','abcdefghigk').group()
Out[41]: 'abcdef'
In [42]: re.match('(ab)cdef','abcdefghigk').group(1)
Out[42]: 'ab'
In [43]: re.match('(ab)*','ababababab').group()
Out[43]: 'ababababab'
命名组和非命名组 格式 : (?P<name>regex)
某些函数可以通过名字提取子组内容,或者通过名字进行键值对的生成。
In [44]: re.match('(?P<word>ab)cdef','abcdefghigk').group()
Out[44]: 'abcdef'
起了名字的子组可以通过名称重复使用
In [45]: re.match('(?P<word>ab)cd(?P=word)','abcdabcdef').group()
Out[45]: 'abcdab'
四、re模块
1、查看re模块常用的方法和属性
In [1]: import re
In [2]: dir(re)
Out[2]:
['A',
'ASCII',
'DEBUG',
'DOTALL',
'I',
'IGNORECASE',
'L',
'LOCALE',
'M',
'MULTILINE',
'S',
'Scanner',
'T',
'TEMPLATE',
'U',
'UNICODE',
'VERBOSE',
'X',
'_MAXCACHE',
'__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'__version__',
'_alphanum_bytes',
'_alphanum_str',
'_cache',
'_cache_repl',
'_compile',
'_compile_repl',
'_expand',
'_locale',
'_pattern_type',
'_pickle',
'_subx',
'compile',
'copyreg',
'error',
'escape',
'findall',
'finditer',
'fullmatch',
'match',
'purge',
'search',
'split',
'sre_compile',
'sre_parse',
'sub',
'subn',
'sys',
'template']
可以通过help查看每一个方法的原型
In [3]: help(re.compile)
compile(pattern, flags=0)
功能 : 获取正则表达式对象
参数 : pattern 正则表达式
flags 功能标志位 提供正则表达式结果的辅助功能
返回值:返回相应的正则对象
* compile 函数返回值的属性函数 和 re模块属性函数有相同的部分
相同点:
*功能完全相同
不同点:
compile返回值对象属性函数参数中没有pattern和flags部分,因为这两个参数内容在compile生成对象时已经指明,而re模块直接调用这些函数时则需要传入
compile返回值对象属性函数参数中有pos和endpos参数,可以指明匹配目标字符串的起始位置,而re模块直接调用这些函数时是没有这个
In [4]: obj = re.compile('abc')
In [5]: obj.findall('abcdefg')
Out[5]: ['abc']
In [6]: re.findall('abc','abcdefg')
Out[6]: ['abc']
In [7]: dir(obj)
Out[7]:
['__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__',
'findall',
'finditer',
'flags',
'fullmatch',
'groupindex',
'groups',
'match',
'pattern',
'scanner',
'search',
'split',
'sub',
'subn']
In [11]: obj.findall('abcdefg',pos = 0,endpos = 20)
Out[11]: ['abc']
In [12]: obj.findall('abcdefg',pos = 4,endpos = 20)
Out[12]: []
findall(string,pos ,endpos)
功能 : 将正则表达式匹配到的内容存入一个列表返回
参数 : 要匹配的目标字符串
返回值: 返回匹配到的内容列表
* 如果正则表达式中有子组,则返回子组的匹配内容
import re
pattern = r'\w+'
#获取正则表达式对象
obj = re.compile(pattern)
l = obj.findall('hello world')
print(l)
['hello', 'world']
import re
pattern = r'(ab)cd(ef)'
#获取正则表达式对象
obj = re.compile(pattern)
l = obj.findall('abcdefg')
print(l)
[('ab', 'ef')]
import re
pattern = r'((ab)cd(ef))'
#获取正则表达式对象
obj = re.compile(pattern)
l = obj.findall('abcdefg')
print(l)
[('abcdef', 'ab', 'ef')]
split()
功能: 以正则表达式切割字符串
返回值 : 分割后的内容放入列表
import re
l = re.split(r'\s+','hello python')
print(l)
['hello',python]
sub(pattern,re_string,string,count)
功能:用目标字符串替换正则表达式匹配内容
参数:re_string 用什么来替换
string 要匹配的目标字符串
count 最多替换几处
返回值 : 返回替换后的字符串
import re
s = re.sub(r'[A-Z]','##','Hi,Jame. It is a fine day')
print(s)
##i,##ame. ##t is atine day
subn()
功能 : 同sub
参数 : 同sub
返回值 : 比sub多一个实际替换的个数
import re
s = re.sub(r'[A-Z]','##','Hi,Jame. It is a fine day',2)
print(s)
s = re.subn(r'[A-Z]','$$','Hi,Jame. It is a fine day',2)
print(s)
s = re.subn(r'[A-Z]','$$','Hi,Jame. It is a fine day')
print(s)
##i,##ame. It is atine day
('$$i,$$ame. It is atine day', 2)
('$$i,$$ame. It is atine day', 3)
groupindex : compile对象属性 得到捕获组名和第几组数字组成的字典
groups: compile属性,得到一共有多少子组
import re
pattern = r'((?P<word>ab)c(?P<test>de)f)'
#获取正则表达式对象
obj = re.compile(pattern)
print(obj.groupindex)
print(obj.groups)
{'test': 3, 'word': 2}
3