正则表达式也叫做REs, regex, 或者regex patterns. 通常正则表达式中出现的任意一个字符代表匹配和他们一样的字符, 但正则表达式也提供了额外的符号来表达更加复杂的含义.
基本符号 以下符号相当于各种编程语言的关键字, 它们并不匹配他们本身
1 . ^ $ * + ? { } [ ] \ | ( )
上述转义字符前加上\可以去除之后的一个字符的转义, 例如 \]
匹配字符 ]
字符类
在 “[“ 和 “]” 中的若干字符构成一个字符类(character class)
一个字符类表示, 此位置可以匹配这个类中的任意一个字符
可以使用-来表示一个范围, 例如[a-c]表示[abc]
在字符类中的特殊符号不被转义
反向匹配
在字符类中, 如果以^开头, 则表示匹配除此字符类中提及的任何其他字符
例如[^5]匹配任何不是5的字符
转义字符
字符
解释
等价正则表达式
\d
匹配任意数字
[0-9]
\D
匹配任意的非数字
[^0-9]
\s
匹配任意空白字符
[ \t\n\r\f\v]
(第一个是空格)
\S
匹配任意非空白字符
[^ \t\n\r\f\v]
\w
匹配任意字符数字(alphanumeric)
[a-zA-Z0-9_]
(最后一个是下划线)
\W
匹配任意非字符数字
[^a-zA-Z0-9_]
说明:这些字符可以和其他字符一样出现在任何合法的地方
高级的转义字符
符号
效果
|
相当于或, A|B表示此处可以匹配A或者B
^
匹配字符串开头
$
匹配字符串结尾
\A
强制匹配字符串开头, 无视MULTILINE标记
\Z
强制匹配字符串结尾, 无视MULTILINE标记
\b
匹配单词边界, 即非字母数字的任意其他字符
\B
匹配非单词边界字符, \b的反义
使用重复功能
符号
效果
*
使此符号之前的字符重复0到多次
+
使此符号之前的字符重复1到多次
?
使此符号之前的字符重复0到1次
{m,n}
使此符号之前的字符重复至少m次, 至多n次(含n)
说明:这些字符都是采用贪婪匹配, 即尽可能多的重复, 从而匹配到最长的符合要求的字符串,如果想要最短匹配们可以在相应的符号后加上一个?
,例如*?
, +?
等
Python和正则表达式 1 2 import rep = re.compile ("ab+" )
在Python中使用正则表达式需要两步, 即
导入re库
编译正则表达式
使用原生字符串 在正则表达式中, 使用\
表示转义, 而在Python中碰巧也使用同样的符号表示转义,因此在正则表达式中, 如果需要使用\
, 在Python的字符串中, 就要输入两个\
, 即\\
为了避免输入太多\导致正则表达式难以理解, 可以使用Python的原生字符串, 即在字符串开头加上r
,例如r"\sda"
,在这个字符串中, 所有字符都是原来的字符, Python不进行任何转义
Re库主要函数功能
函数
说明
re.compile()
将一个字符串编译成正则表达式
re.search()
在一个字符串中搜索匹配的正则表达式的第一个位置, 返回match对象
re.match()
在一个字符串中强制从开始位置起匹配正则表达式, 返回match对象
re.findall()
搜索字符串, 以列表类型返回全部能匹配的子串
re.split()
将一个字符串按照正则表达式匹配结果进行分割, 返回列表类型
re.finditer()
搜索字符串中全部匹配结果, 返回一个迭代类型, 每个迭代元素是match对象
re.sub()
在一个字符串中替换所有匹配正则表达式的子串, 返回替换后的字符串
regex = re.compile(pattern,flags=0)
pattern:正则表达式的字符串或者原生字符串
flags:正则表达式的控制标记
re.search(pattern,string,flags=0)
re.match(pattern,string,flags=0)
re.spilt(pattern,string,maxsplit=0,flags=0)
增加一个新的参数, 表示最大分割数, 其余部分作为最后一个元素输出
re.finditer(pattern,string,flags=0)
参数定义相同, 返回迭代结果, 从而可以用 for in的形式遍历
re.sub(pattern,repl,string,conut=0,flag=0)
repl:需要匹配替换的字符串
count:替换的最大次数
上述返回Match对象的函数如果没有匹配, 则返回None, 从而可以直接使用if语句进行判断是否匹配. 上述标记, 如果在编译字符串的时候就指定, 则函数调用的时候, 就无需再次指定
Match类简介
方法/属性
目的
group()
返回被正则表达式匹配到的字符串
start()
返回匹配的子字符串在字符串中的开始位置
end()
返回匹配的子字符串在字符串中的结束位置
span()
等价于(start(),end())
.string
待匹配字符串
.re
匹配时使用的正则表达式
.pos
正则表达式搜索文本的开始位置
.endpos
正则表达式搜索文本的结束位置
flags常用标记
常用标记(简写/全称)
说明
re.ASCII/re.A
使\w,\b,\s和\d只匹配ASCII字符
re.I/re.IGNORECASE
忽略正则表达式大小写
re.M/re.MULTILINE
使得正则表达式中的^从给定字符串的每一行开始匹配
re.S/re.DOTALL
使得.也可以匹配\n字符
re.VERBOSE/re.X
使正则表达式可以附加解释信息
正则表达式的两种调用方法
函数式用法
面向对象用法
1 2 pat = re.compile (表达式) rst = pat.search(...)
- 因为已经编译了, 所以各个函数, 相比于原来的函数, 就需要去掉表示正则表达式的参数
说明:得益于解释器缓存, 同一个正则表达式, 使用函数式调用时, 不会被多次编译, 因此两种方式的消耗基本相同
VERBOSE模式实例 1 2 3 4 5 6 7 8 9 charref = re.compile (r''' &[#] # start of a numeric entity reference ( 0[0-7]+ #Octal form | [0-9]+ #Decimal form | x[0-9a-fA-F]+ #Hexadecimal form ) ; #Trailing semicolon ''' ,re.VERBOSE)
分组
使用 “(“ 和 “)”可以对一个正则表达式分组, 从而提取出正则表达式匹配的字符串中的部分内容
1 2 3 4 5 6 7 8 9 10 11 >>> m = re.match ("(a(b)c)d" ,"abcd" )>>> m.group(0 )'abcd' >>> m.group(1 )'abc' >>> m.group(2 )'b' >>> m.group(2 ,0 ,2 )('b' , 'abcd' , 'b' ) >>> m.groups()('abc' , 'b' )
在字符串中, 从左向右每遇到一个括号, 序号+1. 使用gruop(i)表示提取第i个括号中匹配的内容
0表示匹配字符串本身, 所以无论正则表达式中是否含有分组, gruop(0)都是存在的
接受多个参数时, 返回多个参数对于的内容的元组
使用groups()返回所有分组匹配的字符串组成的元组(因此不包含直接匹配的正则表达式)
逆向引用(Backreferences)
在一个正则表达式中, 可以使用\1
,\2
等由\
加上一个数字来引用前面出现的分组,表示此处需要匹配前面分组匹配的字符串
1 2 3 >>> p = re.compile (r"(\b\w+)\s+\1" )>>> p.search("Paris in the the spring" ).group()'the the'
括号中需要匹配一个单词, 此后\1表示此处匹配一个和括号相同的单词
Python的扩展正则表达式 注意 :本节内容是正则表达式的扩展用法, 并非标准正则表达式语法
扩展正则表达式符号
符号
作用
(?...)
匹配…中的字符串, 但是不再捕捉其中的内容(语义标记)
(?P<name>...)
匹配…中的字符串, 同时此分组被命名为name
先行断言 先行断言(Lookahead Assertion)是一种特殊的判断方法, 有正向和负向两种方式, 具体如下表
断言表示
类型
含义
(?=…)
正向
匹配…中的正则表达式, 但是不消耗实际字符串的位置, 为真时, 才继续匹配
(?!…)
负向
匹配…中的正则表达式, 当与实际的字符串不匹配时为真, 否则整个正则表达式直接不匹配
扩展阅读 正则表达式扩展阅读 正则表达式扩展阅读
修改字符串 Python字符串相关函数
方法
目的
spilt()
分割字符串, 在匹配正则表达式的字符串处进行分割
sub()
查找匹配正则表达式的子字符串, 并替换为指定的字符串
subn()
和sub()函数效果相同, 增加额外的返回数据参数显示最大匹配次数
spilt(string[,maxsplit=0])
string:待匹配字符串
maxspilt:最大分割数
如果正则表达式中含有捕捉分组, 则每次捕捉的结果会一同返回, 并且正好在两个分割字符串的结果之间
sub(replacement,string[,count=0])
replacement:替换成的字符串
string:待替换字符串
count:最大替换次数
返回替换后的字符串, 如果没有匹配, 返回原来的字符串
subn()
参数和sub()相同
返回一个有两个元素的元组, 第一个元素是替换后的字符串, 第二个元素是替换次数
其他说明
sub函数高级用法
在sub函数的relpacement中, 也可以使用\1,\2等引用正则表达式中的捕捉
如果使用了命名分组, 也可以使用\g<name>
来应用, 注意<>
是必须的
使用\g<2>
与\2
相同, 但可以减少歧义
relpacement也可以是一个接受match对象的函数, 从而实现更加复杂的功能
高级用法实例代码 1 2 3 4 5 6 7 def hexrepl (match ): '''Return the hex string for a decimal number''' value = int (match .group()) return hex (value) p = re.compile (r'\d+' ) p.sub(hexrepl,'Call 65490 for printing, 49152 for user code.' )
正则表达式最佳实践
使用正则表达式还是字符串方法
如果是无差别的文本替换, 应该使用字符串的replace()方法
如果是无差别的单一字符替换, 应该使用字符串的translate()方法
只有当替换操作是特异性的时候, 才应该考虑代价更高的正则表达式方法
match()还是search()
match()只从开始匹配, search()匹配任意位置
只有在确实需要从开头开始匹配, 才应该使用match(), 不要执着于非要只使用match()
正则表达式引擎会使用正则表达式的第一个确定字符进行匹配优化
贪婪匹配还是最小匹配
通常的重复匹配字符串都是贪婪匹配的, 即匹配尽可能长的字符串
在各种重复匹配符后加上一个?表示最小匹配, 例如+?,*?,??或者{m,n}?
最小匹配匹配尽可能短的字符串
使用re.VERBOSE
复杂的正则表达式的可读性较低, 使用测此标记可以增加表达式的可读性
处理字符类中的空白字符, 正则表达式中的所有空白都会被忽略
使用#添加注释
经典正则表达式实例
正则表达式
解释
^[A-Za-z]+$
由26个字母组成的字符串
^[A-Za-z0-9]+$
由26个字母和数字组成的字符串
^-?\d+$
整数形式的字符串
^[0-9]*[1-9][0-9]*$
正整数形式的字符串
[\u4e00-\u9fa5]
判断是不是中文字符
高级正则表达式实例 1 2 3 4 5 6 \s* (?P<header>[^:]+) \s* : (?P<value>.*) \s*$