简介
正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的、高度专业化的编程语言,可通过 re 模块获得。 使用正则,可以为要匹配的可能字符串集指定规则,然后在任何字符串进行匹配。还可以使用正则修改字符串,或以各种方式将字符串拆分。
正则表达式模式被编译成一系列字节码,然后由用 C 编写的匹配引擎执行。正则表达式语言相对较小且受限制,因此并非所有可能的字符串处理任务都可以使用正则表达式完成。
简单模式
先来看看最简单的正则表达式,正则表达式最常用的任务就是匹配字符。
匹配字符
大多数字母和字符只会匹配自己。 例如,正则表达式 test
将完全匹配字符串 test
。
一些字符是特殊的 元字符(metacharacters ),并且不匹配自己。 相反,它们表示应该匹配一些与众不同的东西,或者通过重复它们或改变它们的含义来影响正则的其他部分。
元字符只有14个,完整列表如下:
. ^ $ * + ? { } [ ] \ | ( )
先来看看 [
和 ]
。 它们用于指定字符类,它是你希望匹配的一组字符。 可以单独列出字符,也可以通过给出两个字符并用 ‘-’ 标记将它们分开来表示一系列字符。 例如, [abc]
将匹配任何字符 a、 b 或 c ;这与 [a-c]
相同,它使用一个范围来表示同一组字符。 如果你只想匹配小写字母,可以使用 [a-z]
。
字符类中的元字符不生效。 例如,[akm$]
将匹配 ‘a’ , ‘k’ 、 ‘m’ 或 ‘$’ 中的任意字符; ‘$’ 通常是一个元字符,但在一个字符类中它被剥夺了特殊性。
当 '^'
作为该类的第一个字符时表示字符类中未出现的字符(类似取补集)。 例如,[^5]
将匹配除 ‘5’ 之外的任何字符。 但是!如果 '^'
出现在字符类的其他位置,则它没有特殊含义。 例如:[5^]
将匹配 ‘5’ 或 ‘^’。
.
可以匹配除换行符之外的任何内容,并且有一个可选模式( re.DOTALL
)甚至可以匹配换行符。
|
或者“or”运算符。 如果 A 和 B 是正则表达式,A|B 将匹配任何与 A 或 B 匹配的字符串。 | 具有非常低的优先级,以便在交替使用多字符字符串时使其合理地工作。 Crow|Servo
将匹配 'Crow'
或 'Servo'
,而不是 ‘Cro’、‘w’ 或 ‘S’ 和 ‘ervo’。
$
匹配行的末尾,定义为字符串的结尾,或者后跟换行符的任何位置。
\
可以转义所有元字符,比如使用\[
来匹配[
,使用\\
来匹配\
。有一些以\
开头的特殊序列表示预定义的字符集:
\number
匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如 (.+) \1 匹配 ‘the the’ 或者 ‘55 55’, 但不会匹配 ‘thethe’ (注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 ‘[’ 和 ‘]’ 字符集合内,任何数字转义都被看作是字符。
\A
只匹配字符串开始。
\b
匹配空字符串,但只在单词开始或结尾的位置。一个单词被定义为一个单词字符的序列。注意,通常 \b
定义为 \w
和 \W
字符之间,或者 \w
和字符串开始/结尾的边界, 意思就是 r'\bfoo\b'
匹配 'foo', 'foo.', '(foo)', 'bar foo baz'
但不匹配 'foobar'
或者 'foo3'
。
默认情况下,Unicode字母和数字是在Unicode样式中使用的,但是可以用 ASCII 标记来更改。如果 LOCALE 标记被设置的话,词的边界是由当前语言区域设置决定的,\b
表示退格字符,以便与Python字符串文本兼容。
\B
匹配空字符串,但 不 能在词的开头或者结尾。意思就是 r'py\B'
匹配 'python', 'py3', 'py2'
, 但不匹配 'py', 'py.'
, 或者 'py!'
. \B
是 \b
的取非。
\d
匹配任何十进制数,等价于 [0-9]
。
\D
匹配任何非十进制数字的字符。就是 \d
取非,等价于 [^0-9]
。
\s
匹配任何空白字符,等价于 [ \t\n\r\f\v]
。
\S
匹配任何非空白字符。就是 \s
取非,等价于 [^ \t\n\r\f\v]
。
\w
匹配任何数字和字母和下划线,等价于 [a-zA-Z0-9_]
。
\W
匹配非单词字符的字符。这与 \w
正相反,等价于 [^a-zA-Z0-9_]
。
\Z
只匹配字符串尾。
重复
*
可以指定它前一个字符可以匹配任意次,比如wo*
可以匹配w
(0个o
),wo
(1个o
),woo
(2个o
),wooo
(3个o
)等。*
的重复是贪婪的,匹配引擎会尽可能多的重复它。
+
则是指定它前一个字符可以匹配一次或多次,与*
的区别是无法匹配零次,比如wo+
可以匹配wo
(1个o
),woo
(2个o
),wooo
(3个o
)等,但不能匹配w
(0个o
),。
?
则是匹配零次或一次,比如wo?
匹配w
(0个o
),wo
(1个o
)。
{m,n}
表示至少重复m次,最多重复n次,比如wo{1,3}
可以匹配wo
(1个o
),woo
(2个o
),wooo
(3个o
)。m和n可以省略,省略m表示下限为0,省略n表示上限为无穷大。
使用正则表达式
python标准库中的re
模块提供了正则表达式引擎的接口,允许你将正则编译为对象,然后用它们进行匹配。
编译正则表达式
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换。
>>> import re
>>> p = re.compile(‘ab*’)
>>> p
re.compile(‘ab*’)
反斜杠灾难
正则表达式使用反斜杠字符 \
来表示特殊形式或转义特殊字符。 这与 Python 中\
的使用相冲突。
假设要编写一个与字符串 \section
相匹配的正则,必须传递给 re.compile()
的结果字符串必须是 \\section
,但是,要将其表示为 Python 字符串文字,必须 再次 转义两个反斜杠,最终你写出来的字符串变成"\\\\section"
。
简而言之,要匹配文字反斜杠\
,正则字符串为 '\\\\'
。 在反复使用反斜杠的正则中,这会导致大量重复的反斜杠,并使得生成的字符串难以理解。
解决方案是使用 Python 的原始字符串表示法来表示正则表达式;反斜杠不以任何特殊的方式处理前缀为 'r'
的字符串字面,因此 r"\n"
是一个包含 '\'
和 'n'
的双字符字符串,而 "\n"
是一个包含换行符的单字符字符串。"\\\\section"
可以写为r"\\section"
。
进行匹配
现在我们得到了一个编译正则表达式的对象,该对象有几个方法和属性,最常用的有以下几个:
方法 / 属性
match()
确定正则是否从字符串的开头匹配。
search()
扫描字符串,查找此正则匹配的任何位置。
findall()
找到正则匹配的所有子字符串,并将它们作为列表返回。
finditer()
找到正则匹配的所有子字符串,并将它们返回为一个迭代器(iterator)。
如果没有找到匹配, match()
和 search()
返回 None
。如果它们成功, 一个 匹配对象实例将被返回,包含匹配相关的信息:起始和终结位置、匹配的子串以及其它。
python附带了一个小工具用来测试正则表达式,位于Tools/demo/redemo.py,源代码如下:
#!/usr/bin/env python3
"""Basic regular expression demonstration facility (Perl style syntax)."""
from tkinter import *
import re
class ReDemo:
def __init__(self, master):
self.master = master
self.promptdisplay = Label(self.master, anchor=W,
text="Enter a Perl-style regular expression:")
self.promptdisplay.pack(side=TOP, fill=X)
self.regexdisplay = Entry(self.master)
self.regexdisplay.pack(fill=X)
self.regexdisplay.focus_set()
self.addoptions()
self.statusdisplay = Label(self.master, text="", anchor=W)
self.statusdisplay.pack(side=TOP, fill=X)
self.labeldisplay =