Python中的正则表达式(二)
2020-05-09
作者:老齐
与本文相关的图书推荐:《跟老齐学Python:轻松入门》

在上一篇(《Python正则表达式(一)》)中,已经介绍了正则表达式的基本含义,并且对re模块中的元字符[ ]进行了说明,本文接续上文,介绍有关元字符。
re模块的元字符
点(.)
点.(注意必须是英文状态下的)是一个通配符,即表示了任何符号(换行符除外)。
1 | >>> re.search('foo.bar', 'fooxbar') |
在上面示例中,正则表达式foo.bar表示的匹配规则是:先是三个字符foo,然后用通配符.说明第四个字符可以是除了换行符之外的任何字符,第五个及其后的字符是bar。显然,fooxbar符合这个规则,而foobar和foo\nbar不符合,前者foo之后是b,但b之后是ar而不是bar;后者中间是一个换行符\n。
\w和\W
\w匹配全部由字母和数字组成的字符串,即大写、小写字母以及0到9的数字,注意,也包括下划线。通常,也可以用[a-zA-Z0-9]来替代它。
1 | >>> re.search('\w', '#(.a$@&') |
显然,字符串'#(.a$@&'中只有一个字母,上面演示中也都显示,匹配了字母a。
如果是\W(大写),则意味着与\w相反,不包括字母、数字和下划线。
1 | >>> re.search('\W', 'a_1*3Qb') |
字符串'a_1*3Qb'中的*不属于字母、数字、下划线集合,在上述示例中匹配到了。注意,[^a-zA-Z0-9_]中以^开头,表示对后面字符集合的补集(取反)。
\d和\D
\d匹配由数字组成的字符,与[0-9]相当。\D同样是\d取反,即[^0-9]。
1 | >>> re.search('\d', 'abc4def') |
\s和\S
\s匹配任何空白字符,包括空格、制表符、换行符等等。等价于 [\f\n\r\t\v]。
1 | >>> re.search('\s', 'foo\nbar baz') |
与前面一样,\S也是对\s取反,不匹配任何空白字符。
1 | >>> re.search('\S', ' \n foo \n ') |
上面几个元字符,也可以写到一个集合中。
1 | >>> re.search('[\d\w\s]', '---3---') |
[\d\w\s]的含义就是匹配任何数字、字母和空白字符,-则不在匹配之列。
转义符
跟Python中的字符串中规定一样,在正则表达式中,也用\表示对后面的字符转移。
1 | >>> re.search('.', 'foo.bar') |
第一个示例中的.,表示的是通配符,即任何字符。因此匹配了后面字符串中的第一个f。第二个示例中的\.,因为使用了转移符,它表示要匹配一个英文的句点,不再是通配符了,所以最终匹配了后面字符串中的句点符号。
使用\,需要特别小心。
1 | >>> s = r'foo\bar' |
这里创立了原始字符串s,注意,如果单单看print(s)的结果,容易产生误解。因为这里使用了原始字符串r'foo\bar,其中的\就表示了原本的反斜杠符号,而不是转义符。当执行s时,会看到,Python解析器会将其解析为'foo\\bar',也就是这种方式的字符串和前面定义的原始字符串是一样的,或者说前面定义原始字符串,在Python使用它的时候,会被解析为'foo\\bar',这就是我们要注意的地方。
下面要匹配s里面的\,按照通常方法,这样来试试:
1 | >>> re.search('\\', s) |
出问题了,原因就在于Python解析器实际使用的是'foo\\bar',那么,这里就有了两个反斜杠,第一个反斜杠表示的是“转移符”,并把这个符号传给了re.search(),正则表达式收到了单个反斜杠,但这不是有意义字符,因此会出现混乱,导致了错误。
下面演示两种解决方式:
1 | >>> re.search('\\\\', s) |
或者:
1 | >>> re.search(r'\\', s) |
定位字符
定位字符是零宽度匹配,表示定位的符号不匹配字符串中的任何实际字符,并且不会使用任何搜索字符串。定位字符指示搜索字符串中必须发生匹配的特定位置。
^或\A
^或\A表示匹配输入字符串的开始位置。但是,当它们在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合,即补集或相反。如果要匹配^字符本身,必须要用\^。
1 | >>> re.search('^foo', 'foobar') |
正则表达式^foo表示要匹配以foo开头的字符串,'foobar'符合规则,'barfoo'不符合规则。
\A的作用与^一样。
1 | >>> re.search('\Afoo', 'foobar') |
$或\Z
与前述^相对应,$表示在字符串的结尾部分搜索相应匹配。
1 | >>> re.search('bar$', 'foobar') |
上面的示例中,bar$表示搜索字符串结尾是bar,foobar符合此正则表达式的规则,barfoo则不符合。在这里,\Z与$的效果一样。
但是,如果在下面的示例中,就只能使用$。
1 | >>> re.search('bar$', 'foobar\n') |
\b
\b匹配一个单词(也包括中文字符)的边界,即单词的分界。
例如这样一句话:Laoqi Classroom,其中每个字符都有一个位置,包括空白(空格)也如此。如果某个字符后面的字符不是字母、数字和下划线,即不全是\w所匹配的字符,那么\b就会匹配后面的字符的后面(但不是下一个字符)。例如这句话中i后面是空格,不在\w范围内,那么\b就会匹配空格后面、C前面的位置。
例如:
1 | >>> re.search(r'\bbar', 'foo bar') |
字符串foo bar中有空格,正则表达式r'\bbar'就匹配这个字符后面的位置,并且此位置之后是bar。同理foo.bar亦然。
但是:
1 | >>> print(re.search(r'\bbar', 'foobar')) |
则不然。因为foobar本身没有\b要匹配的位置。
1 | >>> re.search(r'foo\b', 'foo bar') |
按照前述解释,上面示例不难理解。读者可以自己尝试梳理一番。
1 | >>> re.search(r'\bbar\b', 'foo bar baz') |
这几个示例中,则出现了两个\b,其含义是要匹配在bar两侧都能找到“位置”的字符串。
另外,\B则是对\b的取反。
1 | >>> print(re.search(r'\Bfoo\B', 'foo')) |
(未完,待续)
参考资料:https://realpython.com/regex-python/
搜索技术问答的公众号:老齐教室
在公众号中回复:老齐,可查看所有文章、书籍、课程。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
关注微信公众号,读文章、听课程,提升技能