python正则表达式笔记

  1. re模块下的函数
1.1 compile(pattern):创建模式对象
import re

pat = re.compile('A')
m = pat.search('CBA') #等价于 re.search('A','CBA')
print(m)
==> <_sre.SRE_Match object; span=(2, 3), match='A'>  #匹配到了,返回MatchObject(True)

m=pat.search('CBD')
print(m)
==> None
1.2 search(pattern,string):在字符串中寻找模式
m = re.search('asd','ASDasd')
print(m)
==>  <_sre.SRE_Match object; span=(3, 6), match='asd'>  #匹配到了,返回MatchObject(True)

m = re.search('asd','ASDASD')
print(m)
==>  None  #没有匹配到,返回None(False)
1.3 match(pattern,string):在字符串开始处匹配模式
m = re.search('asd','ASDasd')
print(m)
==>  <_sre.SRE_Match object; span=(3, 6), match='asd'>  #匹配到了,返回MatchObject(True)
m = re.search('asd','ASDASD')
print(m)
==>  None  #没有匹配到,返回None(False)

等价

pat = re.compile('a')
print(pat.match('Aasd'))
==>  None
print(pat.match('aASD'))
==>  <_sre.SRE_Match object; span=(0, 1), match='a'>

上面的函数返回都可以在if条件语句中进行判断:

if pat.search('asd'):
...     print('OK')
... 
OK        #找到返回
if re.search('a','ASD'):
...     print("OK")
...       #没有找到
1.4 split(pattern,string):根据模式分割字符串,返回列表
re.split(',','a,s,d,asd')
==>  ['a', 's', 'd', 'asd']  #返回列表 
pat = re.compile(',')
pat.split('a,s,d,asd')
==>  ['a', 's', 'd', 'asd']   #返回列表
 
re.split('[, ]+','a ,  s  ,d     ,,,,,asd')   #正则匹配:[, ]+,后面说明
==>  ['a', 's', 'd', 'asd']
 
re.split('[, ]+','a ,  s  ,d     ,,,,,asd',maxsplit=2)  #maxsplit 最多分割次数
==>  ['a', 's', 'd     ,,,,,asd']
 
pat = re.compile('[, ]+')   #正则匹配:[, ]+,后面说明
pat.split('a ,  s  ,d     ,,,,,asd',maxsplit=2) # maxsplit 最多分割次数
==>  ['a', 's', 'd     ,,,,,asd']
1.5 findall(pattern,string):列表形式返回匹配项
re.findall('a','ASDaDFGAa') 
==>  ['a', 'a']  #列表形式返回匹配到的字符串
pat = re.compile('a')
pat.findall('ASDaDFGAa')
==>  ['a', 'a']  #列表形式返回匹配到的字符串

pat = re.compile('[A-Z]+')  #正则匹配:'[A-Z]+' 后面有说明
pat.findall('ASDcDFGAa')
==>  ['ASD', 'DFGA']   #找到匹配到的字符串
pat = re.compile('[A-Z]')
pat.findall('ASDcDFGAa')  #正则匹配:'[A-Z]+' 后面有说明
==>  ['A', 'S', 'D', 'D', 'F', 'G', 'A']  #找到匹配到的字符串

pat = re.compile('[A-Za-z]')  #正则匹配:'[A-Za-z]+' 匹配所有单词,后面有说明
pat.findall('ASDcDFGAa')
==>  ['A', 'S', 'D', 'c', 'D', 'F', 'G', 'A', 'a'] 
1.6 sub(pat,repl,string) :用repl替换 pat匹配项
re.sub('a','A','abcasd')   #找到a用A替换,后面见和group的配合使用
==> 'AbcAsd'
 
pat = re.compile('a')
pat.sub('A','abcasd')
==>  'AbcAsd'
 
pat=re.compile(r'www\.(.*)\..{3}') #正则表达式
#在Python的string前面加上‘r’, 是为了告诉编译器这个string是个raw string,不要转译反斜杠 '\' 。
#例如,\n 在raw string中,是两个字符,\和n, 而不会转译为换行符。
#由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上'r'。    
#与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。
#假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":
#前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
#Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。
#同样,匹配一个数字的"\\d"可以写成r"\d"。
#有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。   
#不是说 加了r \就没有转译功能,好乱,就直接记住1句话:
#当一个字符串使用了正则表达式后,最好在前面加上'r',这样你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观 
pat.match('www.dxy.com').group(1)
==>  'dxy'
re.sub(r'www\.(.*)\..{3}',r'\1','hello,www.dxy.com')
pat.sub(r'\1','hello,www.dxy.com') 
==>  'hello,dxy'
# r'1' 是第一组的意思
#通过正则匹配找到符合规则的"www.dxy.com" ,取得 组1字符串 去替换 整个匹配。 
pat=re.compile(r'(\w+) (\w+)')     #正则表达式
s='hello world ! hello hz !'
 
pat.findall('hello world ! hello hz !')
==>  [('hello', 'world'), ('hello', 'hz')]
pat.sub(r'\2 \1',s)                #通过正则得到组1(hello),组2(world),再通过sub去替换。即组1替换组2,组2替换组1,调换位置。  
==>  'world hello!hz hello!'
1.7 escape(string) :对字符串里面的特殊字符串进行转义
re.escape('www.dxy.cn')
==>  'www\\.dxy\\.cn'   #转义

上面的函数中,只有match、search有group方法,其他的函数没有。

  1. 一些常用表达式用法
2.1 [^pattern]

中括号里面以^开头后接一个pattern,表示匹配不是pattern的字符

例子

有这样一个字符串s = "[王小明]Nh 问 [深圳]Ns 和 [成都]Ns的 天气 和 怎么 到 [深圳 腾讯 公司]Ni"

匹配出里面所有的符合这种[xxx]Ns模式

可以利用这个解决,其中'[^\[]'表示所有不是'\['的字符,'['前面加'\'表示转义

s = "[王小明]Nh 问 [深圳]Ns 和 [成都]Ns的 天气 和 怎么 到 [深圳 腾讯 公司]Ni" 
patt = re.compile('\[[^\[]*\]Ns')
patt.findall(s)
Out: ['[深圳]Ns', '[成都]Ns']
2.2 利用()分组

2.1中的例子结果为 ['[深圳]Ns', '[成都]Ns'],如果我们只想要[xxx]Ns模式中的xxx呢,可以在正则表达式中加上一个(),进行分组取

代码如下

s = "[王小明]Nh 问 [深圳]Ns 和 [成都]Ns的 天气 和 怎么 到 [深圳 腾讯 公司]Ni" 
patt = re.compile('\[([^\[]*)\]Ns')
patt.findall(s)
Out[54]: ['深圳', '成都']
2.3 零宽断言
  • (?=pattern) 零宽正向断言
  • (?!pattern) 零宽负向断言

断言的意思是判断是否满足,零宽的意思是它只匹配位置,如同^匹配开头,$匹配末尾一样,只是一个位置,不返回匹配到的字符,正向表示需要满足pattern,负向表示不能满足pattern,注意,在python这个断言语句可以放到期望返回的匹配模式的后面或者前面,其他语言可能区分先行和后行断言(也就是这个断言语句可以放到期望返回的匹配模式前面和后面写法有点不一样)。

例子

有字符串“asdf /aa/bb/cc/xxxxx/ afsdfa”, 未知有多少个"/",从行尾向前匹配,替换倒数第二个“/”为ABC,如何做到?

利用零宽断言解决:

s = 'a/aa/bb/cc/xxxxx/afsdfa'
patt = re.compile(r"(?=.*)/(?=[^/]*/[^/]*$)")
patt.search(s)
输出: <_sre.SRE_Match object; span=(10, 11), match='/'>

可以看到匹配的结果位置为span=(10, 11),为倒数第二个'/'

 

附:

1、在线正则表达式测试 http://tool.oschina.net/regex/#

2、正则表达式中的向前匹配、向后匹配、负向前匹配、负向后匹配 https://blog.csdn.net/kinglyjn/article/details/54692371

 

posted @ 2018-08-15 11:27  viczhang  阅读(372)  评论(0编辑  收藏  举报