版本:v1.0
摘要
本文主要介绍了Python中的正则表达式re模块,详细解释其用法,包括其下各种函数,比如re.findall,re.search,re.match等等。
2013-09-05
修订历史 | ||
---|---|---|
修订 1.0 | 2013-09-05 | crl |
|
版权 © 2013 Crifan, http://crifan.com
目录
表格清单
将下面帖子内容整理合并进来:
之前抽空写了,Python中的正则表达式的系列教程。
暂时没写完,但是也算写了不少了。
现在整理出,已经写出的部分,供参考:
【教程】详解Python正则表达式之: '.' dot 点 匹配任意单个字符
【教程】详解Python正则表达式之: '^' Caret 脱字符/插入符 匹配字符串开始
【教程】详解Python正则表达式之: '$' dollar 美元符号 匹配字符串末尾
【教程】详解Python正则表达式之: '*' star 星号 匹配0或多个
【教程】详解Python正则表达式之: [] bracket 中括号 匹配某集合内的字符
【教程】详解Python正则表达式之: '|' vertical bar 竖杠
【教程】详解Python正则表达式之: (…) group 分组
【教程】详解Python正则表达式之: (?…) extension notation 扩展助记符
【教程】详解Python正则表达式之: (?:...) non-capturing group 非捕获组
【教程】详解Python正则表达式之: (?P<name>…) named group 带命名的组
【教程】详解Python正则表达式之: (?P=name) match earlier named group 匹配前面已命名的组
【教程】详解Python正则表达式之: (?(id/name)yes-pattern|no-pattern) 条件性匹配
【教程】详解Python正则表达式之: (?=…) lookahead assertion 前向匹配 /前向断言
【教程】详解Python正则表达式之: (?!…) negative lookahead assertion 前向否定匹配 /前向否定断言
【教程】详解Python正则表达式之: (?<=…) positive lookbehind assertion 后向匹配 /后向断言
【教程】详解Python正则表达式之:\s 匹配任一空白字符
【教程】详解Python正则表达式之:re.LOCALE re.L 本地化标志
【教程】详解Python正则表达式之:re.UNICODE re.U 统一码标志
另外,也针对re模块中的一些功能,比如findall,进行了整理:
【整理】Python中的re.search和re.findall之间的区别和联系 + re.finall中带命名的组,不带命名的组,非捕获的组,没有分组四种类型之间的区别
还有些和group相关的内容:
摘要
摘要
其实,Python中的正则表达式的语法,
和通用的正则表达式的语法,
基本没太大区别。
下面,再详细的解释一下,Python中的正则表达式的语法:
下面总结一些Python中的正则表达式相对于其他语言中的正则表达式的一些特点,包括优点和缺点:
所以对于字符串中,有双引号的,可以在写字符串最外层用单引号括起来,而不需要用反斜杠了。
反之,如果需要表示的其中包括单引号,那么最外层用双引号,所以,还是很方便的。
其实,其详细语法,可以参考Python自带的帮助(help)文件
可以通过在帮助文件的搜索框中输入re,然后就可以找到“(re.MatchObject attribute)”,双击,即调转到对应的re模块的内容的详细解释部分了。
关于re模块的基本语法,简单总结如下:
表 2.1. Python中re模块中的特殊字符
. | 匹配任意字符 | ||||
[] | 用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字符集,对于字符集中的字符可以理解成或的关系 | ||||
^ |
|
||||
$ | 匹配字符串的末尾,或者匹配换行之前的字符串末尾 | ||||
* | 对于前一个字符重复0到无穷次 | ||||
+ | 对于前一个字符重复1到无穷次 | ||||
? | 对于前一个字符重复0到1次 | ||||
{m,n} | 对于前一个字符重复次数在为m到n次。
|
表 2.2. Python中re模块中特殊转义序列(字符)
\A | 匹配字符串的开头 |
\b | 匹配一个空字符(仅对一个单词word的开始或结束有效) |
\B | 与\b含义相反 |
\d | 匹配任何十进制数;它相当于类 [0-9] |
\D | 匹配任何非数字字符;它相当于类 [^0-9] |
\s | 匹配任何空白字符;它相当于类 [ \t\n\r\f\v] |
\S | 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v] |
\w | 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_] |
\W | 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_] |
\Z | 匹配字符串的结尾 |
目录
摘要
此处整理一下,Python中使用正则表达式的心得:
某次,对于字符串
footerUni=u"分类: | 标签:";
使用:
foundCatZhcn = re.search(u"分类:(?P<catName>.+)|", footerUni); print "foundCatZhcn=",foundCatZhcn; if(foundCatZhcn): print "foundCatZhcn.group(0)=",foundCatZhcn.group(0); print "foundCatZhcn.group(1)=",foundCatZhcn.group(1); catName = foundCatZhcn.group("catName"); print "catName=",catName;
所得到的结果却是:
foundCatZhcn= <_sre.SRE_Match object at 0x027E3C20> foundCatZhcn.group(0)= foundCatZhcn.group(1)= None catName= None
其中group(0),不是所期望的整个匹配的字符串,且group(1)应该是一个空格的字符,而不是None。
调试了半天,最后终于找到原因了,原来是在正则搜索中,竖线"|",是or的关系
“'|'
A|B, where A and B can be arbitrary REs, creates a regular expression that will match either A or B. An arbitrary number of REs can be separated by the '|' in this way. This can be used inside groups (see below) as well. As the target string is scanned, REs separated by '|' are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the '|' operator is never greedy. To match a literal '|', use \|, or enclose it inside a character class, as in [|].
”所以此处匹配到的结果是空值
所以测试过程中,无论如何修改re中的表达式,也都会得到foundCatZhcn是非空的值
然后对应的解决办法是,给竖线加上反斜杠,表示竖线字符本身:
foundCatZhcn = re.search(u"分类:(?P<catName>.*?)\|", footerUni);
这样才能真正自己想要的效果。
参考这里:
Match Object Methods | Description |
---|---|
group(num=0) | This methods returns entire match (or specific subgroup num) |
groups() | This method return all matching subgroups in a tuple (empty if there weren’t any) |
知道了,原来group(0),是所有匹配的内容,而group(N)指的是原先subgroup子组对应的内容,而subgroup是原先search等规则中,用括号()所括起来的。
举例1:
#!/usr/bin/python import re line = "Cats are smarter than dogs"; matchObj = re.search( r'(.*) are(\.*)', line, re.M|re.I) if matchObj: print "matchObj.group() : ", matchObj.group() print "matchObj.group(1) : ", matchObj.group(1) print "matchObj.group(2) : ", matchObj.group(2) else: print "No match!!"
输出是:
matchObj.group(): Cats are matchObj.group(1) : Cats matchObj.group(2) :
举例2:字符串:
var pre = [false,'', '','\/recommend_music/blog/item/.html'];
然后去search:
match = re.search(r"var pre = \[(.*?),.*?,.*?,'(.*?)'\]", page, re.DOTALL | re.IGNORECASE | re.MULTILINE)print "match(0)=", match.group(0),"match(1)=",match.group(1),"match(2)=",match.group(2),"match(3)=",match.group(3)
得到的输出是:
match(0)= var pre = [false,'', '','\/recommend_music/blog/item/.html'] match(1)= false match(2)= \/recommend_music/blog/item/.html match(3)=
关于search的结果,第 6.2 节 “re模块的search的含义和用法及查找后group的含义”中已经解释过了。
下面详细给出关于findall中,对于pattern中,加括号,与不加括号,所查找到的结果的区别。
其中加括号,表示()内的匹配的内容为一组,供得到结果,通过group(N)所获取的到,N从0开始。
下面是详细测试结果,看结果,就明白是否加括号之间的区别了:
# here blogContent contains following pic url link: # http://hiphotos.baidu.com/againinput_tmp/pic/item/069e0d89033b5bb53d07e9b536d3d539b400bce2.jpg # http://hiphotos.baidu.com/recommend_music/pic/item/221ebedfa1a34d224954039e.jpg # following is test result: pic_pattern_no_parenthesis = r'http://hiphotos.baidu.com/\S+/[ab]{0,2}pic/item/[a-zA-Z0-9]{24,40}\.\w{3}' picList_no_parenthesis = re.findall(pic_pattern_no_parenthesis, blogContent) # findall result is a list if matched print 'findall no()=',picList_no_parenthesis print 'findall no() len=',len(picList_no_parenthesis) #print 'findall no() group=',picList_no_parenthesis.group(0) # -> cause error pic_pattern_with_parenthesis = r'http://hiphotos.baidu.com/(\S+)/([ab]{0,2})pic/item/([a-zA-Z0-9]+)\.([a-zA-Z]{3})' picList_with_parenthesis = re.findall(pic_pattern_with_parenthesis, blogContent) # findall result is a list if matched print 'findall with()=',picList_with_parenthesis print 'findall with() len=',len(picList_with_parenthesis) #print 'findall with() group(0)=',picList_with_parenthesis.group(0) # -> cause error #print 'findall with() group(1)=',picList_with_parenthesis.group(1) # -> cause error print 'findall with() [0][0]=',picList_with_parenthesis[0][0] print 'findall with() [0][1]=',picList_with_parenthesis[0][1] print 'findall with() [0][2]=',picList_with_parenthesis[0][2] print 'findall with() [0][3]=',picList_with_parenthesis[0][3] #print 'findall with() [0][4]=',picList_with_parenthesis[0][4] # no [4] -> cause error
测试结果为:
findall no()= [u'http://hiphotos.baidu.com/againinput_tmp/pic/item/069e0d89033b5bb53d07e9b536d3d539b400bce2.jpg', u'http://hiphotos.baidu.com/recommend_music/pic/item/221ebedfa1a34d224954039e.jpg'] findall no() len= 2 findall with()= [(u'againinput_tmp', u'', u'069e0d89033b5bb53d07e9b536d3d539b400bce2', u'jpg'), (u'recommend_music', u'', u'221ebedfa1a34d224954039e', u'jpg')] findall with() len= 2 findall with() [0][0]= againinput_tmp findall with() [0][1]= findall with() [0][2]= 069e0d89033b5bb53d07e9b536d3d539b400bce2 findall with() [0][3]= jpgpattern = re.compile(r'HTTP Error ([0-9]{3}):.*') matched = re.search(pattern, errStr) if matched : #注意,此处运行时候会直接出错!!!因为search查找后,应该用matched.group(0),matched.group(1)等方式查看查找出来的结果 print 'is http type error' isHttpError = True else : print 'not http type error' isHttpError = False
用re.search后,想要查看结果,如果直接用返回值matched的话,运行的时候会直接出错!!! 因为search查找后,应该用matched.group(0),matched.group(1)等方式查看查找出来的结果。 这点,需要特别注意。
【后记】
后来的测试结果表明上面的判断是错误的。
上面的错误实际上是由于当时search的时候所传入的参数errStr实际上是个对象类型,而不是普通的str或者unicode字符类型,所以导致上面的search会直接运行出错。
而如果在search之前,用errStr = str(errStr)后,search的结果,则是可以直接拿来判断是否为空,或者用来打印的。
相应的打印出来的结果,是类似这样的:
matched= <_sre.SRE_Match object at 0x02B4F1E0>
而对应的,matched.group(0)是对应的匹配此次查找的全部的字符:
HTTP Error 500: ( The specified network name is no longer available. )
【总结】
在调用类似于re.search等函数的时候,要确保传入的所要查找的变量,是字符类型(str或者是unicode),否则,像我这里,传入的是一个对象,而不是字符,就会导致运行出错了。
字符串变量respPostJson为:
,url : 'http:\/\/hi.baidu.com\/shuisidezhuyi\/item\/d32cc02e598460c50e37f967',
使用代码:
foundUrlList = re.findall("url\s*?:\s*?'(?P<url>http:\\/\\/hi\.baidu\.com\\/.+?\\/item\\/\w+?)'", respPostJson); logging.info("foundUrlList=%s", foundUrlList);
却搜不到对应的字符串,结果为:
foundUrlList=[]
而只有给斜杠前面加上反斜杠:
foundUrlList = re.findall("url\s*?:\s*?'(?P<url>http:\\\/\\\/hi\.baidu\.com\\\/.+?\\\/item\\\/\w+?)'", respPostJson); logging.info("foundUrlList=%s", foundUrlList);
才可以搜索到结果:
foundUrlList=['http:\\/\\/hi.baidu.com\\/shuisidezhuyi\\/item\\/d32cc02e598460c50e37f967']
很是奇怪。目前不知道为何会这样,等待高手给解释解释。