1.什么是正则表达式
正则表达式(regular expression)是一种用于匹配文本形式的强大逻辑表示,在Python中的re模组提供了正则表达式的支持。
正则表达式由一些普通字符和一些元字符(meta characters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊含义。
当正则表达式为一个普通的字符串时,一个正则表达式的匹配行为就是一个普通的字符串查找过程,如正则表达式“testing”中没有包含任何元字符,它可以匹配“testing”和“testing123”等字符串,但因为大小写敏感,它不能匹配“Testing”。其他一些元字符则不会被作为普通字符来处理,它们包括 . ^ $ + ? { [ ] \ | ( ) 。
. | 匹配除了换行以外的任何字符 |
\w | 等价于[a-zA-Z0-9_]会匹配单一字母、数字或下划线字符,而\W则会匹配任何非字母、数字和下划线的单一字符 |
\b | 匹配“单一字母、数字或下划线字符”和“任何非字母、数字和下划线的单一字符” |
\s | 等价于 [ \n\r\t\f],会匹配一个空白字符(包括空格、换行、返回、制表符、表格),\s则会匹配所有非空白字符 |
\t | 匹配制表符 |
\n | 匹配换行符 |
\r | 匹配返回符 |
\d | 等价于[0-9]用于匹配十进制表示的数字 |
^作为开始标记,$作为结束标记,分别用于标记一个字符串的开始和结束的位置。 \ 用于一些字符的转移,比如 \. 表示对于一个真实点字符的匹配, \\ 表示对一个真实反斜杠字符的匹配等。如果对不是很确定一些字符是否需要进行转义才能匹配,大可都加上斜杠,比如对于 @ ,写成\@是一定没有问题的。
2.正则表达式查找
结果为
3.基础正则使用
结果如右
4.正则表达式重复
*和+可实现重复多次的表达,
*表示对它之前一个字符有0或更多次的重复
+表示对它之前一个字符有1或更多次的重复
后者print的寻找的形式是p后跟了至少一个i的连续个i的形式。
结果为
5.正确的正则表达式
6.正则里的方括号
一些正则符号等价于一些方括号包括的正则字符,方括号将一系列的正则字符以"或"关系组织在一起。
除了在方括号内一一列举的方式,还可以采用横线来标识一个范围。
结果为
7.正则提取
对于一个正则表达式的匹配过程中,在其中添加几对圆括号,用于指定几个具体的匹配的部分。
如果不看圆括号,我们这里实际上去对邮件地址进行了匹配,而圆括号匹配了@前的部分和之后的部分。
结果
8.正则表达式的调试
正则表达式用简单的一些字符的组合包含了太丰富的语义,但他们是在太过密集了,为了写对挺费时。有以下调试方法。
可以设计一些列放在列表里的字符串用于调试,其中一部分是可以产生符合正则表达式的结果的,另一部分是产生不符合正则表达式的结果的。请注意,在设计这些字符串时,尽可能让他们的特征表现得更为不同一些,便于覆盖到我们可能出现的各种正则表达式没有写对的错误。
例如,对于一个存在+的正则表达式,我们可以考虑用一个符合 * 但是不符合+的字符串。
然后可写一个循环,一次验证每个列表内的字符串是否符合指定的某个正则表达式并且和你设定的存在另一个列表内的预期结果进行对比,如果出现了不一致的情况,则你应该考虑看看你的正则表达式是否还需要修改,如果结果基本一致,可以考虑进一步修改我们用于调试的字符串或添加新的字符串。
9.查找所有方法
除了search方法,在结合圆括号后,还能用名为findall的方法来匹配查找出所有的被查找字符串符合正则的结果,并得到一个结果元组为元素的列表。
结果如右
10.在文件中查找
11.选项与贪心匹配
在用于正则表达式的re模组中的函数有一些可选参数,我们可以对search()函数或者findall()函数传入额外的参数来进行使用,如re.search(pat,str,re.IGNORECASE)中的re.IGNORECASE就是使用了re中的一个标记作为额外的参数。
在re模组中,提供了很多不同的可选参数,其中上面提到的IGNORECASE表示了让匹配时忽略大小写的区别;而另外一个可选参数DOTALL如果被添加,则会允许正则中的 . 去跨行匹配,加了这个参数后 .* 这样的匹配方式,将可以跨行进行匹配,而不只是在行内进行。另外,还有一个可选参数是MULTILINE,使用它后,对于一个多行文本组成的字符串, ^和$ 将可以用于匹配每一行的开始和结束,而如果没有用它时 ^ 和 $ 值会匹配整个字符串的开始和结束。
除了可选参数,还需理解正则匹配的“贪心情况”。假设有一段文字<b>foo</b> and <i>so on </i>而你希望匹配 (<.*>) 提取所有的HTML 标签, 我们可以得到<b>,</b>,<i>,</i>的结果吗?
因为 .* 这样的匹配时“贪心的”,它会尽可能去得到较长的匹配结果,因此我们会得到的是一整个 <b>foo</b> and <i>so on </i> 作为匹配出的结果。如果我们希望得到期望中的结果,我们就需要这个匹配时非贪心的,在正则表达式中,我们对于 * 和+ 这种默认贪心的匹配可以加上? 使之变为不贪心的。
即如果我们将 (<.*>) 改为 (<.*?>) ,正则表达式会先匹配<b>,然后匹配</b>,接下来则分别是 <i>和</i>。这样的匹配结果与我们的预期完全一致。相应的,对于一些用到了+的情况,我们可以将+ 变成 +?来进行非贪心的匹配。