不管哪一种语言,在使用正则表达式的时候都避免不了一个问题,就是在匹配元字符的时候,须要对元字符进行转义,让python
正则表达式引擎将其当作普通字符来匹配。本文主要以python为例,说明一下转义中须要注意的问题。正则表达式
python的正则表达式中须要转义的元字符有如下几个:spa
python中对元字符的转义使用双反斜杠 \\ 来表示code
# 普通元字符的转义 _string = ''' !@#$%^& ''' # 不转义 print re.findall('$', _string) #>>> ['', ''] # 双反斜杠转义 print re.findall('\\$', _string) #>>> ['$'] # 单反斜杠转义 print re.findall('\$', _string) #>>> ['$']
看上面的例子你们可能会发现,使用一个反斜杠 \ 也能够达到转义的效果,那为何还要写两个呢?这得先搞清楚pythonblog
的字符串转义(不是正则表达式转义),python自己使用 \ 来转义一些特殊字符,好比在字符串中加入引号的时候,为了字符串
s = 'i\'m superman' print s #>>> i'm superman
防止和字符串自己的引号冲突,使用 \ 来转义,通常状况下这个也不会引发什么问题,可是当你要使用 \ 来转义 \ 的时候,get
就比较混乱了,好比咱们想要输出一个 \ ,得写两个 \ ,不然会报语法错误,由于 \ 把后面的引号给转义了,必须使用 \ string
# 错误写法 # print '\' # 正确写法 print '\\' #>>> \ # 原生字符串 print r'\\' #>>> \\
将 \ 转义一下使其不具有转义功能,才能够正确输出,当使用原生字符串的时候,输出显示了两个 \ ,看起来好像是写几个class
输出几个的样子,若是这样想的话,你能够试一下,看能不能输出奇数个 \。语法
先来讲一下什么是原生字符串,其实就是不进行特殊处理的字符串,所谓特殊处理,貌似就是针对转义的,原生字符串
的诞生自己就是为了解决转义的时候写了太多 \ 的问题,可是为何使用了原生字符串仍然不能只输出一个 \ 呢?其实这应
该算是一个bug,就是python的字符串不能以奇数个 \ 结尾,这样的写法会被认为是将结尾的引号进行了转义,致使语法错
误。具体能够参考http://t.cn/RfolM3H。
虽然原生字符串并非很完美,但它已经能够帮咱们解决很大一部分问题了。好比当你想匹配 \ 的时候,原生字符串可
_string = '\\\\' print _string #>>> \\ # 字符串 for i in re.findall('\\\\', _string): print i #>>> \ #>>> \ # 原生字符串 for i in re.findall(r'\\', _string): print i #>>> \ #>>> \
以让你少写一半的 \ ,既节省代码量,又增长可读性。
说了这么多也没说为何在写正则表达式的时候一个 \ 也能够起到转义的做用。咱们先来分析一下一个字符串被正则表
达式引擎解析的过程,一共有4步:
# 字符串 # '\\\\' # 通过python处理以后 # '\\' # 正则表达式引擎接收到的 # '\\' # 正则表达式引擎进行转义处理后 能够匹配到 \ # '\'
而当使用原生字符串的时候就变为了3步
# 原生 # '\\' # 再也不处理 # '\\' # 正则表达式引擎接收到的 # '\\' # 正则表达式引擎进行转义处理 # '\'
下面是最重要的一个,当使用一个 \ 转义的时候,python会识别不了转义序列,因而它就不作任何处理,直接传给了
正则表达式引擎。这就解释了为何一个 \也能够转义。这个不算bug,虽然方便了使用,但会让人很迷惑,有利有弊吧。
# 原生 # '\$' # 识别不了 不进行处理 # '\$' # 正则表达式引擎接收到的 # '\$' # 正则表达式引擎进行转义处理 # '$'
下面举几个例子看一下
# 匹配 \d+ _string = 'i am \d+' print re.findall('\\\\d\\+', _string)[0] #>>> \d+ print re.findall(r'\\d\+', _string)[0] #>>> \d+ # 匹配 [] _string = 'i am []' print re.findall('\\[\\]', _string)[0] #>>> [] print re.findall('\[\]', _string)[0] #>>> [] print re.findall(r'\[\]', _string)[0] #>>> []