使用正则表达式
如今咱们开始来写一些简单的正则表达式吧。Python 经过 re 模块为正则表达式引擎提供一个接口,同时容许你将正则表达式编译成模式对象,并用它们来进行匹配。
小甲鱼解释:re 模块是使用 C 语言编写,因此效率比你用普通的字符串方法要高得多;将正则表达式进行编译(compile)也是为了进一步提升效率;后边咱们会常常提到“模式”,指的就是正则表达式被编译成的模式对象。
编译正则表达式
正则表达式被编译为模式对象,该对象拥有各类方法供你操做字符串,如查找模式匹配或者执行字符串替换。
html
re.compile() 也能够接受 flags 参数,用于开启各类特殊功能和语法变化,咱们会在后边一一介绍。
如今咱们先来看个简单的例子:python
正则表达式做为一个字符串参数传给 re.compile()。因为正则表达式并非 Python 的核心部分,所以没有为它提供特殊的语法支持,因此正则表达式只能以字符串的形式表示。(有些应用根本就不须要使用到正则表达式,因此 Python 社区的小伙伴们认为没有必要将其归入 Python 的核心。)相反,re 模块仅仅是做为 C 的扩展模块包含在 Python 中,就像 socket 模块和 zlib 模块。
使用字符串来表示正则表达式保持了 Python 简洁的一向风格,但也所以有一些负面影响,下边咱们就来谈一谈。
麻烦的反斜杠
上一篇中咱们已经提到了,正则表达式使用 '\' 字符来使得一些普通的字符拥有特殊的能力(例如 \d 表示匹配任何十进制数字),或者剥夺一些特殊字符的能力(例如 \[ 表示匹配左方括号 '[')。这会跟 Python 字符串中实现相同功能的字符发生冲突。
小甲鱼解释:挺拗口,接着看例子你就懂了~
如今的状况是,你须要在 LaTeX 文件中使用正则表达式匹配字符串 '\section'。由于反斜杠做为须要匹配的特殊字符,因此你须要再它前边加多一个反斜杠来剥夺它的特殊功能。因此咱们会把正则表达式的字符写成 '\\section'。
但不要忘了,Python 在字符串中一样使用反斜杠来表示特殊意义。所以,若是咱们想将 '\\section' 完整地传给 re.compile(),咱们须要再次添加两个反斜杠......
正则表达式
匹配字符 | 匹配阶段 |
\section | 须要匹配的字符串 |
\\section | 正则表达式使用 '\\' 表示匹配字符 '\' |
"\\\\section" | 不巧,Python 字符串也使用 '\\' 表示字符 '\' |
简而言之,为了匹配反斜杠这个字符,咱们须要在字符串中使用四个反斜杠才行。因此,在正则表达式中频繁地使用反斜杠,会形成反斜杠风暴,进而致使你的字符串极其难懂。
解决方法是使用 Python 的原始字符串来表示正则表达式(就是在字符串前边加上 r,你们还记得吧...):
socket
正则字符串 | 原始字符串 |
"ab*" | r"ab*" |
"\\\\section" | r"\\section" |
"\\w+\\s+\\1" | r"\w+\s+\1" |
小甲鱼解释:强烈建议使用原始字符串来表达正则表达式。
实现匹配
当你将正则表达式编译以后,你就获得一个模式对象。那你拿他能够用来作什么呢?模式对象拥有不少方法和属性,咱们下边列举最重要的几个来说:
学习
方法 | 功能 |
match() | 判断一个正则表达式是否从开始处匹配一个字符串 |
search() | 遍历字符串,找到正则表达式匹配的第一个位置 |
findall() | 遍历字符串,找到正则表达式匹配的全部位置,并以列表的形式返回 |
finditer() | 遍历字符串,找到正则表达式匹配的全部位置,并以迭代器的形式返回 |
若是没有找到任何匹配的话,match() 和 search() 会返回 None;若是匹配成功,则会返回一个匹配对象(match object),包含全部匹配的信息:例如从哪儿开始,到哪儿结束,匹配的子字符串等等。
接下来咱们一步步讲解:
spa
如今,你能够尝试使用正则表达式 [a-z]+ 去匹配各类字符串。
例如:code
由于 + 表示匹配一次或者屡次,因此空字符串不能被匹配。所以,match() 返回 None。
咱们再尝试一个能够匹配的字符串:htm
在这个例子中,match() 返回一个匹配对象,咱们将其存放在变量 m 中,以便往后使用。
接下来让咱们来看看匹配对象里边有哪些信息吧。匹配对象包含了不少方法和属性,如下几个是最重要的:
对象
方法 | 功能 |
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
你们看:blog
因为 match() 只检查正则表达式是否在字符串的起始位置匹配,因此 start() 老是返回 0。
然而,search() 方法可就不同咯:
在实际应用中,最经常使用的方式是将匹配对象存放在一个局部变量中,并检查其返回值是否为 None。
形式一般以下:
有两个方法能够返回全部的匹配结果,一个是 findall(),另外一个是 finditer()。
findall() 返回的是一个列表:
findall() 须要在返回前先建立一个列表,而 finditer() 则是将匹配对象做为一个迭代器返回:
小甲鱼解释:若是列表很大,那么返回迭代器的效率要高不少。迭代器的相关知识请看:《零基础入门学习Python》048 | 魔法方法:迭代器