什么是正则表达式
正则表达式(regular expressions)是一种符号表示,用有限的符号来代表一种字符串的匹配模式,从而能够识别进而处理更加复杂的模式。在现在nlp技术逐步发展的背景下,对于源数据的处理越发重要,正则表达式也更应该被掌握。很多语言,比如python java perl,都通过一些函数支持正则表达式的处理。本篇只谈及python的re库
怎么写正则表达式
正则表达式本质上就是一个字符串,和代码一样,只不过python的代码要送进python的解释器,而正则表达式的字符串要送进re的引擎。基于这个本质,我们可以写第一个正则表达式:
pattern = '123' # 正则表达式
sentence = 'first123rear'
re.search(pattern, sentence)
如果看过其他人写的正则表达式,有时候会发现他们的pattern
并不是简单的字符串,而是在前面有一个r。具体而言,是这样的
pattern = r'123'
这个`r``代表的意思是raw,实际上,如果我们的正则表达式没有***的话,有没有这个r没有任何差异。但是,我们知道在python中这个符号的地位比较特殊,叫转义符,如果我们在普通的字符串中想表达***,我们实际上会写两个,就像这样:
example = '\\something'
进一步,我们需要了解python里面的re具体是怎么一个工作流程:
- 所有代码,包括正则表达式送进python解释器
- pattern送进re引擎
- re引擎编译表达式
这里会有一个问题,对于re引擎而言,\ 也是转义符,换言之,如果想匹配一个\,必须保证正则表达式在送进re引擎的时候是这样的:\\。但是问题在于,在第一步送进python解释器的时候,\\已经被理解成了\,这就意味着送进re引擎的正则表达式只有一个\,进而出现未知的错误。比如:sre_constants.error: bad escape (end of pattern) at position 0
为了解决这个问题,有两种方法
- 用传统字符串,写成
'\\\\'
,这样在通过第一步python解释器的时候会被解释为**\**,这样就以正确的方式送到了re引擎中。 - 用raw字符串,raw字符串不会被python解释器瞎搞,你写的是什么就是什么,换言之
r'\\'
和'\\\\'
是等价的,一般我们为了看着方便习惯用raw字符串进行表达。
常用的表达
[]
中括号表达一个集合,以字符为基本单位。比如:
pattern = re.compile(r'fa[rsfa]t')
pattern.search('fart')
具体而言,这个表达式的含义为:我在找一个以fa开头,t结尾,中间有rsfa任何一个字符的字串。实际上,这个表达式可以匹配:fart, fast, faft, faat这四种字串。
进一步,在中括中,有一些特殊的表达方式,比如:
[0-9]
, [a-z]
, '[A-Z]'
, 分为表示任何一个数字、小写字母、大写字母,当然,也可以这么写:[0-9a-zA-Z]
,用来表达匹配任何一个数字和字母
.
这个点是通配符的意思,匹配任意一个字符,除了换行符**\n**
\w \W
\w == [0-9a-zA-Z_],包括所有数字和字母加上下划线
\W 代表所有非这些字符
\d \D
\d == [0-9] 匹配一个数字
\D 代表非数字
\s \S
\s 代表任何一个空白字符,比如空格,\t,\n
\S 代表任何一个非空白字符
^ \A
代表以后面的字符为起始串,
pattern = re.compile(r'^in')
pattern.search('instant')
\A和^基本一致,是平替,但是在多行模式下略有不同
$ \Z
到表以其为结尾的前面的字符
pattern = re.compile(r'tant$')
pattern.search('instant')
类似的,二者在多行模式下略有不同,此外,\Z还会额外匹配一个换行,即
pattern = re.compile(r'tant\Z')
pattern.search('instant\n')
\b \B
b是boundary的意思,代表边界,只能在正则表达式的头或者尾部出现,能匹配到空格、点、括号等字符
pattern = re.compile(r'\bstant')
pattern.search('in stant')
pattern.search('instant')
\B匹配非boundary
*
代表之前的字符出现任意次,包括零次
+
之前表达式出现至少一次
?
之前的表达式出现0、1次