目录
浮点数(负号的时候整数部分不能没有,正数的时候,整数部分可以没有)
使用正则表达式的思考流程:
做分解,分析子问题,套入各种元字符等,调试。
元字符
特殊单字符
. :换行以外任意单个字符
\d :任意单个数字。\D :任意非数字。
\w:任意单个数字或字母或下划线。\W:任意非数字字母下划线。
\s:任意单个空白符。\S:任意非空白符。
空白符
\r:回车符。
\n:换行符。
\f:换页符。
\t:制表符。
\v:垂直制表符。
\s:任意空白符。
量词
*含义:0到多次
+含义:1到多次
?含义:0到1次,如colou?r
{m}含义:出现m次
{m,}含义:出现至少m次
{m,n}含义:m到n次
范围
| :或,如ab|bc代表ab或bc
[...]:多选一,括号中任意元素
[a-z]:匹配a到z之间的任意单个元素
[^...]:取反,不能是括号中的任意单个元素
断言
贪婪(尽可能最长匹配)与非贪婪(尽可能最短匹配)
贪婪(greedy)表示次数的量词默认是贪婪的,在贪婪模式下,会尝试尽可能最大长度区匹配。
re.findall(r'a*', 'aaabb')
结果如下:[’aaa‘, '', '', '']
非贪婪匹配(lazy)在量词后面加上英文问号,表示使用非贪婪量词。
re.findall(r'a*?', 'aaabb')
结果如下:[’a', 'a', 'a', '', '', '']
独占模式
分组与引用
分组就是加括号,并且将其中的内容表示为一个整体,并且可以被复用。
比如:
\d{15}(\d{3})?
如果不想子组被保存,可以这样
\d{15}(?:\d{3})?
如果想使用之前保存的自组,使用\数字,表示1使用第几个子组,第几个根据括号确定。
比如:
(\w+)\1
匹配两个连续的单词。
也就是the little cat cat里面的cat cat。
匹配模式
不区分大小写
((?i)cat)\1。匹配的是:类似CAT CAT
(?i)(cat)\1。匹配的是:类似CAT Cat
((?i)the) cat
注释
(?#xxxxx)表示注释
比如
(\w+)(?#word)\1(?#word repeat again)
断言
单词边界
\btom\b,这个正则只能匹配tom,不能匹配tomorrow里的tom。
行的开始\结束
环视
(?<=Y):表示左边是Y
(?<!Y):表示左边不是Y
(?=Y):右边是Y
(?!Y):右边不是Y
比如
(?<!\d)\d{6}(?!\d)
匹配一个左右没有数字的六位数。
优化方法
测试性能
使用ipython
import re
x = '-' * 1000000 + 'abc'
timeit re.search('abc', x)
提前编译
尽量准确表示匹配范围
提取出公共部分
出现可能性大的放左边
只在必要时使用子组
警惕嵌套的子组重复
避免不同分支重复匹配
常见问题以及解决方案
匹配正数,负数和小数
[-+]?\d+(?:\.\d+)?
非负整数
[1-9]\d* | 0
非正整数
-[1-9]\d* | 0
浮点数(负号的时候整数部分不能没有,正数的时候,整数部分可以没有)
-?\d+(?:\.\d+)? | \+?(?:\d+(?:\.\d+)?|\.\d+)
负浮点数
-\d+(?:\.\d+)?
正浮点数
\+?(?:\d+(?:\.\d+)?|\.\d+)
十六进制数
[0-9A-Fa-f]+
手机号码
身份证号码
[1-9]\d{14}(\d\d[0-9Xx])?
中文字符
[\u4E00-\u9FFF]