python 正则表达式(三)

[python]  view plain  copy
  1. 注意:我用的python版本为3.6.  

刚开始学习正则表达式的时候不太认真,致使没记住多少哭,后面我老师带咱们搞数据挖掘时,才发现书到用时方恨少,赶忙又把正则表达式梳理了一遍,我我的比较喜欢用一些小例子去理解掌握知识点,因此这篇文章没什么描述,直接经过代码来学习知识,一半批注我都写在代码旁边的注释里了。html

分组捕获 或非捕获

In [21]:
#()表示分组,前面未来对单个字符的重复[1,2],若是你想重复一个子串的话,就能够采用分组的方法
#(字符串)量词 表示对字符串重复
p=re.compile('(ab)+')    #匹配一个以上的ab
print(p.search('acabababc').span())   #成功
p=re.compile('(ab|bc)+')      #匹配一个以上的ab和bc
print(p.search('acababababc').span())
(2, 8)
(2, 10)
'''
分组除了当作了表达式外,还有一个重要的功能就是记录。
(和)中匹配的内容会被记录下来,以备之后引用。
在python中,MatchObject的方法group(),start(),end(),span()能够传入一个整型参数来
获得这些记录
记录以0开始计数,而且0表示整个匹配了的表达式,是这些方法的缺省参数,分组从左到右
从1开始计数
'''
p=re.compile('(a(b)c)d')
m=p.search('abcd')
print(m.groups())   #各分组的值
print(m.group())
print(m.group(0))
print(m.group(1))
print(m.group(2))

结果:python

('abc', 'b')
abcd
abcd
abc
b
#(?:....)表示非记录分组,即这个分组不会被记录下来
m=re.match('([abc])+','cbaeee')
print(m.group())
print(m.groups())
print(m.group(0))    #0与不写参数效果同样,都是表示 the entire matching string
print(m.group(1))
print('=======')
n=re.match('(?:[abc])+','abc')   #分组不会被记录
print(m.group(0))
print(m.groups())
print(m.group(1))

结果:正则表达式

cba
('a',)
cba
a
=======
cba
('a',)
a
'''
在正则表达式中,还能够对分组作出向后引用,是用'\数学'来表示。即\1表示第1个分组,\2表示第二个等等

'''
p=re.compile(r'(\b\w+)\s+\1')    #匹配两个一样的单词连着出现,即找一个单词,而且在若干空格,仍是一样的单词
print(p.search('Paris in the the spring').group())
print(p.search('Paris in the the spring').groups())

结果:spring

the the
('the',)
#命名分组    (?P(<name>....)和(?P=name)
'''
(?P<name>...)用来定义一个命名分组,他能够经过MatchObject的方法group('name')获得,
同时,在表达式中,也能够以用(?P=name)来表示对它的引用。
'''
p=re.compile(r'(?P<word>\b\w+\b).*(?P=word)')    #注意命名分组对它的引用
m=p.search('((((Lots of punctuation aLots)))')
print(m.group())
print(m.group('word'))  #在方法中以引用
print(m.group(0))
print(m.group(1))
print(m.span('word'))

结果app

Lots of punctuation aLots
Lots
Lots of punctuation aLots
Lots
(4, 8)

前,后向界定(能够理解为一种条件)

In [52]:
#(?=...)后向界定/零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式
#但它不包括这些表达式,就像\b,^,$那样用于指定一个位置,这个位置应该知足必定的条件(断言)
#所以他们也被成为0度断言
#好比\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing之外的部分)
p=re.compile('(Rui) (?=Zhang)')   #匹配Rui后面跟zhang时的状况不包括张在内
print(p.search('hi,Rui Zhang').group())
print(p.search('hi,Rui Zhang').group(0))
print(p.search('hi,Rui Zhang').group(1))
print(p.search('hi,Rui Zhang').groups())   #全部知足条件的分组
print(p.search('hi,Rui Zhou').group())       #匹配失败
Rui 
Rui 
Rui
('Rui',)
#(?!...)
'''
后向非界定/零宽度负预测先行断言。断言此位置的后面不能匹配表达式
例如:\d{3}(?!\d)匹配三位数字,并且这三位数字的后面不能是数字
'''
p=re.compile(r'Rui(?!Zhang)')     #匹配Rui后面不是Zhang的状况
print(p.search('hi,Rui Zhou').group())   #成功
print(p.search('hi,Rui Zhang').group())    #失败

结果:ide

Rui
#(?<!...)前向非界定/零宽度负回顾后发断言,断言此位置的前面而不能匹配表达式
#例如:(?<![a-z])\d(7)匹配前面不是小写字母的七位数字
p=re.compile(r'(?<!Rui )Zhang')
print(p.search('hi,Shan Zhang').group())   #成功
print(p.search('hi,Rui Zhang').group())     #匹配失败
结果:
Zhang

#(?iLmsux)
'''
在'i','L','m','s','u','x'中的一个或多个,它不匹配任何字串,而是表示对应(re.I,re.M,re.S,re.X,re.U)的6种选择
此处编译选项'i'等价于IGNORECASE,L等价于LOCAL,m等价
于MULTLINE,s的等价于DOTALL,u等价于UNICODE,x等价于VERBOSE
请注意他们的大小写,在使用时能够指定一部分,不如只指定忽略大小写,可写为'(?i)',要同时忽略大小写并使用多行模式
另外要注意选项的有效范围是整条规则,即写在规则的任何地方,选项都会对所有整条正则式有效
'''
p=re.compile('(?m)^From:')   #与使用re.M选项是同样的
print(p.search('hi,\nFrom:rui').span())

结果:学习

(4,9)
# I IGNORECASE 忽略大小写
#  L LOCAL字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的
#好比在转义字符\w,在英文环境下,它表明[a-zA-Z0-9],即全部英文字符和数字
#若是在一个法语环境下使用,缺省设置下,不能匹配'e'或‘c’.加上这L选项和就能够匹配了,不过这个对弈中文环境彷佛没什么用,它仍然不能匹配
# M MULTLINE多行匹配,在这个模式下‘’(表明字符串开头)和‘$’(表明字符串结尾)将可以匹配多行匹配的状况,成为行首和行尾标记
s='123 56\4n789 012\n345 678'
rc=re.compile('^\d+')   #匹配一个位于开头的数字,没有使用M选项   \d[0-9]
print(rc.findall(s))
rcm=re.compile('^\d+',re.M)  #找到了三个行首的数字
print(rcm.findall(s))
结果:
['123']
['123', '345']

'''
一样,对于'$'来讲。没有使用M选项,它将匹配最后一个行尾的数字,即'678'
加上之后,就能匹配三个行尾的数字 456 012 和678 了
'''
rc=re.compile('\d+$')
print(rc.findall(s))
rcm=re.compile('\d+$',re.M)
print(rcm.findall(s))
结果:
['678']
['012', '678']

# S DOTALL ‘.’号将匹配全部的字符,缺省状况下'.'匹配除换行符'\n'之外的全部字符
#  U UNICODE \w,\W,\b,\B,\D,\s和\S都将使用Unicode
#  X VERBOSE  这个选项忽略规则表达式中的空白,并容许使用‘#’来引导一个注释,这样可让你把规则写的更美观些。