匹配字符串中的/**,对比以下三种用法。
import re
s = 'justfortesting/**csdopov**/python'
# 第一种方式
re.findall('/\\*\\*',s)
[out]: ['/**']
# 第二种方式
re.findall(r'/\*\*',s)
[out]: ['/**']
# 第三种方式
pattern = re.escape('/**')
re.findall(pattern,s)
[out]: ['/**']
以上三种用法实际上是等价的,但是前两者用法的正确使用的前提是正确的知道字符串转义和正则转义的知识,而第三种用法则直接使用正则表达式的re.escap(str)函数,这样只要我们传入想要匹配的str参数,该函数就可以返回正确的字符串转义前和正则转义前的字符串。这里的str内容是我们想要匹配的字符串转义前的字符串(即并非字面的,而是在字符串转义语境下的),比如输入str为'\n',则是字符串转义语境下的换行符,而不是字面的\和n。为了更深入的了解escape函数的设计机制,我们看如下例子。
import re
# 第一种方式
pattern = re.escape('\n') # 这时如果在交互窗口下输入pattern回车查看其内容,那么显示的是
# 转义前(字符串转义和正则转义)字符串'\\\n'
re.findall(pattern,'\n')
[out]: ['\n']
# 第二种方式
re.findall('\\\n','\n')
[out]: ['\n']
# 第三种方式
re.findall('\\n','\n')
[out]: ['\n']
以上三种方式中,第一种和第二种是等价的,因为pattern实际上就是'\\\n',但是我们发现第三种方式也是可以匹配到换行符的。这是因为正则语法的\n也表示换行符,即兼容字符串中的换行符。但是escape函数的设计是对于所有的字符串的,所以对于不兼容的字符,其也要保证正确性,因此如果str是特殊字符,那么对于正则来说,需要在其前面加入转义符\将其转为字符串意义下的字符,所以再回溯到字符串转义,正则中\的成功加入需要在转义前字符串中加入\\,因此对于特殊字符,escape函数都会在其前面多出两个转义符。更简单一点的比如re.escape('*'),返回的就是'\\*'。
综上我们知道,对于正则表达式中的字符串转义和正则转义之间,是具有不太容易一下子搞清楚的关系的,所以如果不想理解这层关系,又保证正确的使用正则匹配,规范的用法是使用escape函数进行匹配字符到转义前字符的转化,然后再将得到的转义前字符作为参数传给匹配函数。由于escape函数返回的是转义前字符串,因此再将其结合原生字符串一起使用,是正则匹配最为规范的用法,如下所示,compile函数中对于正则表达式使用原生字符串,并且字符串的格式化表达中传入的字符串也是用escape函数返回的字符串,即转义前字符串搭配转义前字符串,这是最为正确的组合,也是python正则匹配中最为推荐的规范用法。
import re
def process(start,end,f):
start = re.escape(start)
end = re.escape(end)
pattern = re.compile(r'%s(?:.|\s)*?%s'%(start,end))
s = f.read()
updated = ''.join(re.split(pattern,s))
return updated