搜索选项
大小写无关匹配
通过上面的学习我们都知道了,只要在pattern中输入除规则用到的字符外,那么肯定就需要匹配这个字符,但其实re.compile()函数还有一个参数,设置该参数可以忽略掉一定的规则。比如,在pattern中输入大写的字母“T”,那么肯定的小写就不会匹配,但是博主就像匹配大写与小写,怎么办?
用前文的知识,我们可以用"[]"或进行操作。但学习了re.compile()函数的另一个参数,我们只需要设置该参数就行,具体代码如下:
import re content = "This text" pattern = r"T\w+" regex = re.compile(pattern, re.IGNORECASE) match = regex.findall(content) print(match)
运行之后,效果如下:
感兴趣的可以删除re.IGNORECASE参数,看看是不是只有This。
其他匹配规则
除了大小写匹配之外,还有re.compile()函数还提供了其他参数。如下表所示:
参数 |
含义 |
re.IGNORECASE(re.I) |
忽略大小写匹配 |
re.MULTILINE(re.M) |
多行匹配(比如有末尾符号"$",它就会匹配每一行的末尾) |
re.ASCII(re.A) | 让\w,\W,\b,\B,\d,\D,\s和\S 执行ASCII-只匹配完整的Unicode匹配代替。这仅对Unicode模式有意义,而对于字节模式则忽略。 |
re.DOTALL(re.S) |
使’.‘特殊字符与任何字符都匹配,包括换行符;没有此标志,’.'将匹配除换行符以外的任何内容。 |
re.VERBOSE(re.X) |
注释会被忽略(比如为了让字符串可读性更高,程序员可以在字符串中标记注释,使用该参数可以忽略这些注释进行匹配,注释的规则与python代码注释一样) |
前后向断言
在网页爬虫中,假如我们需要匹配链接的标签,往往都是成对的出现才会进行匹配。所以,这个时候只有两个尖括号都出现或者都不出现时表达式才能匹配。
前向断言语法为:(?=pattern)
import re contents = [ "aaa <a href='www.baidu.com'/>", "a href='www.baidu.com'/", "bbb <a href='www.baidu.com'/>", "ccc <a href='www.baidu.com'", ] pattern = r"(?=<).*(?<=>)" for content in contents: regex = re.compile(pattern) match = regex.findall(content) print(match)
运行之后,效果如下:
当然,前向断言还给我们提供了前向否定断言,其语法为(?!pattern)。代码如下:
import re contents = [ "<a href='www.baidu.com'/>", "a href='www.baidu.com'/", "<a href='www.baidu.com'/>", "ccc <a href='www.baidu.com'", ] pattern = r"(?!<).*(?<!>)" for content in contents: regex = re.compile(pattern) match = regex.findall(content) print(match)
运行之后,效果如下:
这样就不需要匹配前后<>了。常用的断言如下表所示:
断言语法 |
含义 |
(?=pattern ) | 后向断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。 |
(?!pattern ) | 后向否定断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配,而不与该数字匹配 。 |
(?<=pattern ) | 前向断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。 |
(?<!pattern ) | 前向否定断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配 |
自引用表达式
在前面,我们学习了分组的知识,但假如有两个分组完全一样,我们还写两遍不成?所以,正则表达式给我们提供了自引用表达式,让我们使用\num编号引用前面的表达式。示例如下:
import re content = "123.123.123.123" pattern = r"(\d{1,3})(.\1){3}" regex = re.compile(pattern) match = regex.findall(content) print(match)
运行之后,输出如下:
需要注意博主前面的提示,“两个分组完全一样”,不仅正则表达式一样,连内容也一样。才能使用自引用表达式,不然,仅仅只是正则表达式一样,内容不一样,也不会匹配。因为自引用表达式引用的是前面正则表达式匹配的内容,并不是引用的正则表达式。这一点需要额外注意,如果需要匹配完全相同的表达式,就需要使用前后断言进行处理。
sub(模式修改字符串)
在实际的文本处理中,我们有时候是提取符合条件的数据,有时候只是修改数据。如果修改数据,就需要用到sub()函数将一个模式的所有出现替换成另一个字符串。示例如下:
import re content = "**blod** **li**" pattern = r"\*{2}(.*?)\*{2}" regex = re.compile(pattern) match = regex.sub(r'<b>\1<b>',content) print(match)
运行之后,效果如下:
这样,我们就给字符串替换了标签。