python正则剖析
基础知识
常用部分剖析
- ^ 匹配字符串的开头
- $ 匹配字符串的末尾
- . 匹配任意字符,除了换行符,当flag=re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。如:
1 | s = '''aaa4a1234 |
- […] 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’
1 | s = 'Abcde' |
- [^…] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符
1 | s = 'Abcde' |
- exp* 匹配0个或多个的表达式
1 | s = 'A4d' |
- exp+ 匹配1个或多个的表达式
1 | s = 'A43d' |
exp? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
例1:
1 | s = 'A43d' |
例2:
1 | s = 'A3d' |
- exp{n} 精确匹配n个前面表达式
- exp{n, } 匹配n到正无穷个exp表达式
- exp{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
1 | s = 'A4321d5' |
- {n,m}? 启用非贪婪模式,即只匹配n次
- a|b 匹配a或b,
1 | s = 'A4321d5' |
常用或操作理解
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 或操作的常用方法,及再次对分组和小括号不表示分组的理解
demo_str = 'abcgraysgreyxz'
print re.findall(r'gr(a|e)(?#aasd)y', demo_str)
print re.findall(r'gr(?:a|e)(?#aasd)y', demo_str)
print re.findall(r'gr[ae]y', demo_str)
print re.findall(r'gray|grey', demo_str)
"""
输出:
['a', 'e'], 剖析: 因为 ()表示分组,表示从源字符串中截取一个子串
['gray', 'grey'] 剖析:(?:exp)不表示分组,这里的exp仅仅是a或e
['gray', 'grey'] 剖析: [exp]的简单用法
['gray', 'grey'] 剖析: |的简单用法
"""(exp) 匹配exp,并捕获文本到自动命名的组里,主要是用于,从一个源字符串中,匹配出子串
1 | s = 'A4321d5' |
- 分组指定别名及反向引用用法
1 | 例1 |
- (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
1 | 例1: |
- (?#…) 注释.
1 | s = 'A4321d5 asd321' |
- \w 匹配字母数字及下划线
1 | s = 'A4321d5&as-d3_21' |
不常用部分符合含义
- \W 匹配非字母数字及下划线
- \s 匹配任意空白字符,等价于 [\t\n\r\f].
- \S 匹配任意非空字符
- \d 匹配任意数字,等价于 [0-9]
- \D 匹配任意非数字
- \A 匹配字符串开始
- \Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
- \z 匹配字符串结束
- \G 匹配最后匹配完成的位置
- \b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’
- \B 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
- \n, \t, 等. 匹配一个换行符。匹配一个制表符。等
常用匹配模式剖析
- re.I 使匹配对大小写不敏感
1 | s = 'Http://www.baidu.com' |
- re.M 多行匹配,影响 ^ 和 $
1 | s = '''aaa4a1234a |
- re.S 使 . 匹配包括换行在内的所有字符, 多行匹配(最为常用的一种模式)
1 | s = '''aaa4a1234a |
贪婪和懒惰的区别
懒惰和贪婪的区别,贪婪可以理解成在匹配一个字符串的时候,心很大,想尽可能多的往后匹配满足条件的字符串,而懒惰可以理解成,在从一个字符串中匹配一截字符串的时候,匹配到第一个满足条件的子串,就保留下结果,继续往后寻找其它满足条件的子串, 一般有?的都表示懒惰。1
2
3
4
5
6
7
8
9
10
11
12
13
14# 举例说明:
demo_str = 'I am Shirley Hilton. I am his wifeasd'
print re.findall(r'i.*e', demo_str) #贪婪模式
#输出 ['irley Hilton. I am his wife'],
# 表示匹配第一个i开始,尽可能多的往后匹配e,直到找到最后一个满足条件的e
print re.findall(r'i.*?e', demo_str) #懒惰模式
# 输出 ['irle', 'ilton. I am his wife'],
# 从左到右匹配到i,然后往右扫描,发现有e结尾满足条件的子字符串,就将结果加入到结果集列表
# 下面也是贪婪模式的一些规则
demo_str = 'asd123456fgh'
print re.findall(r'\d{1,}', demo_str) #贪婪模式,输出 ['123456']
print re.findall(r'\d+', demo_str) #贪婪模式,输出 ['123456']
两条懒惰模式语句剖析
1 | print re.findall(r'\d.*?', demo_str) #懒惰模式,输出 ['1', '2', '3', '4', '5', '6'] |
从以上输出结果,可以引申出 .+?和.*?的区别
- .? 因为 在这里表示前面的字符.重复0到n次,但是这里有?表示懒惰匹配,所以n的值要尽可能的小,所以以上例子输出结果为[‘12’, ‘34’, ‘56’]
- .+? 因为+在这里表示前面的字符.重复1到n次,但是这里有?表示懒惰匹配,所以n的值要尽可能的小,这里n取1,所以以上例子输出结果为[‘12’, ‘34’, ‘56’]
常用python API
- pattern
1 | s = 'abc def ghi' |
- match, 这个方法将从string的pos下标处起尝试匹配pattern;如果pattern结束时仍可匹配,则返回一个Match对象;如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None,多用于验证
1 | line = "dogs Cats are smarter than dogs"; |
- search, 用于在字符串中搜索子串,搜索到第一个就停止搜索,返回匹配的子串
1 | line = "Cats are smarter than dogs"; |
- split, 按照能够匹配的子串将string分割后返回列表
1 | s = 'one1two2three3four4' |
- findall, 查找源字符串中所有满足条件的子串
1 | s = 'one1two2three3four4' |
- sub, 替换
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0。
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换。
1 | # repl 为字符串 |
- subn, 返回 (sub(repl, string[, count]), 替换次数)。
1 | p = re.compile(r'(\w+) (\w+)') |
零宽断言
断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配, 只是匹配位置,并不消费字符
- (?=exp) 匹配exp前面的位置
1 | s = "I'm singing while you're dancing." |
- (?<=exp) 匹配exp后面的位置
1 | s = "I'm reading a book." |
- (?!exp) 匹配后面跟的不是exp的字符串
1 | s = 'abcd1234def567c' |
- (?<!exp) 断言此位置的前面不能匹配表达式exp
1 | s = 'a1234b567' |