python re 模块及正则表达式调用认识(1)

来源:互联网 发布:诗琳通公主的爱情 知乎 编辑:程序博客网 时间:2024/04/29 08:11

        最近用到正则表达式,虽然看了学习了一些,但是不成体系,没有深刻认识,所以来看官方文档学习下,进行一个半汉化的翻译吧,网上查了很多都不是特别全面,要不就不是纯粹用在python中。

http://docs.python.org/2/library/re.html?highlight=re#re

       Both patterns and strings to be searched can be Unicode strings as well as 8-bit strings. 处理对象是unicode或者8位字符串与普通正则不同,python可以使用prefixed with'r' 即r‘XXXX 来代替反斜杠\ ,因为 "\\\\" 才能表示一个’\\‘ ,pattern string 大部分都 use Python’s raw string notation forregular expression patterns;

>>> print "\\n"\n>>> print r"\n"\n>>> 
以上便是 r 的使用,可以减少一根反斜杠。

>>> len ('\n')1>>> len (r'\n')2
因而字符串长度有些区别,会被加1;


中文范围 : [\u4e00-\u9fa5]
         这里注意下 python 的re写的时候 要  u"[\u4e00-\u9fa5]" #确定正则表达式也是 unicode 的


7.2.1 正则表达式语法

RE对特定的字符串集进行匹配,这个模块提供了一个函数来检查特定的字符串是否与给定的表达式相匹配。

re可以串联起来形成新的正则表达式,如A,B分别是正则表达式,合起来AB也是正则表达式。基于此,复杂的正则表达式可以由简单的表达式组合而成,但是其中要排除边界条件,优先级,分组等影响;

下面进行正则格式的一个简介,更多信息参考:Regular Expression HOWTO.

正则表达式包含普通字符和特殊字符。普通字符直接匹配本身,比如 ‘last’ 匹配‘last’。

>>> print re.search('last','dfdfdlast;ini').group(0)    #直接匹配last>>> print re.search('last','dfdfdladst;ini').group(0)           #没有匹配成功,因为没有lastTraceback (most recent call last):  File "<pyshell#9>", line 1, in <module>    print re.search('last','dfdfdladst;ini').group(0)AttributeError: 'NoneType' object has no attribute 'group'>>> print re.search('last','dfdfdladst;ini')             #没有匹配成功None>>> 

一些字符比如‘|’,‘(’之类的是特殊字符,他们有时作为类的普通字符,有时又会影响他周围的正则表达式进行正确的匹配。正则表达式的pattern strings可能不包含空字节,但是可以通过 \ 数字 来实现对null byte 的表示,如‘\x00’。

>>> string = '\x00'+ r'\\'>>> string'\x00\\\\'>>> print string X    #会有一个乱码>>> print re.findall(r'[\x00\x5c]',string)  #上面的意思应该是可以用ascii码来进行正则的书写;['\x00', '\\', '\\']>>> #这个\x00是nul,\x5c是\,python表示方法不同而已,
对于汉字也可以书写正则,具体还没有仔细使用过,编辑器暂不支持。
[\xe000-\x9fcf]+ 就是查汉字的

特殊字符有:

‘.'  ---一般情况下匹配除了newline以外的任何字符,如果 DOTALL 标志被指定,则匹配任何,包括newline换行符。

>>> print re.search(r'las.','dflast ini',re.S).group()#一个点匹配一个字符last>>> print re.search(r'las...','dflast ini',re.S).group()#3个点匹配3个字符,包含一个空格last i>>> print re.search(r'las.....','dflast \niop',re.S).group()#加了S可以匹配换行符\nlast io>>> print re.search(r'las.....','dflast \niop').group() #去掉标志位后出错Traceback (most recent call last):  File "<pyshell#28>", line 1, in <module>    print re.search(r'las.....','dflast \niop').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 
为了看得直观,当然以上多个点可以用其它方式表示,后面讨论。

’^' ---匹配字符串的开始,在MULTILINE模式下,也匹配每一newline。

>>> print re.search(r'^last','lastert \nlastiop').group()  #匹配字符串开始的第一个lastlast>>> print re.search(r'^last','llllastert\nlastiop',re.M).group()  # M模式,匹配了第二行行首的lastlast>>> print re.search(r'^last','llllastert\nlastiop').group()   #去掉M后匹配失败Traceback (most recent call last):  File "<pyshell#37>", line 1, in <module>    print re.search(r'^last','llllastert\nlastiop').group()AttributeError: 'NoneType' object has no attribute 'group'

‘$' ---匹配字符串的结尾或者字符串结尾的newline之前,在MULTILINE模式下,也匹配newline的前面部分

>>> print re.search(r'.iop$','llllastermiop \nlastiop').group()  #匹配结尾tiop
>>> string = '''llllastermioplastiop         #为什么没有匹配tiop???????werttr'''>>> print re.search(r'.iop$',string,re.M).group()   #匹配换行符的前面部分miop
为什么没有匹配tiop???????


foo匹配foo,也可以是foobar。而正则foo$只配foo. 

>>> print re.search(r'foo$','foo').group()foo>>> print re.search(r'foo$','foobar').group() #匹配失败Traceback (most recent call last):  File "<pyshell#56>", line 1, in <module>    print re.search(r'foo$','foobar').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 

在 'foo1\nfoo2\n' 中用foo.$进行匹配可以得到foo2,但在MULTILINE模式中得到的是foo1. 对$在’foo\n‘中进行searching,则会匹配到两个空白,一个在新行之前,一个在字符串的结尾。

>>> print re.search(r'foo.$','foo1\nfoo2\n').group()foo2>>> print re.search(r'foo.$','foo1\nfoo2\n',re.M).group()foo1>>> >>> print re.search(r'$','foo1\nfoo2\n').group()>>>

'*' ----匹配前一个字符0次或无限次

>>> print re.search(r'fo*','foooo').group()foooo>>> print re.search(r'fo*','f').group()  #可以匹配前一个字符零次f>>> 

’+‘----匹配前一个字符1次或无限次。ab+将匹配a之后的b至少一次。

>>> print re.search(r'fo+','foooo').group()foooo>>> print re.search(r'fo+','f').group()Traceback (most recent call last):  File "<pyshell#67>", line 1, in <module>    print re.search(r'fo+','f').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 

’?‘----匹配前一个字符0次或一次。ab? 将匹配a 或者ab

>>> print re.search(r'fo?','foooo').group()fo>>> print re.search(r'fo?','f').group()f>>> 

*?, +?,?? ---- '*','+','?'都是贪婪匹配限定符;尽可能多的匹配内容,但有时候没必要这样,’<.*>'对'<H1>title</H1>'进行匹配,将会匹配整个字符串不只是'<H1>',对其限定符后添加‘?’,这样就会得到非贪婪匹配或者得到最小匹配。尽可能的少匹配字符;用.*?在表达式之前,则会只匹配'<H1>'

>>> print re.search(r'fo*?','foeeeerrfoeeb').group() # *匹配零次f>>> print re.search(r'fo*?','foooorrfooob').group()f>>> print re.search(r'fo+?','foeeeerrfoeeb').group() # + 匹配一次fo>>> print re.search(r'fo+?','foooorrfooob').group()fo>>> print re.search(r'fo??','foeeeerrfoeeb').group() # ?匹配一次f>>> print re.search(r'fo??','foooorrfooob').group()f>>> 
>>> print re.search(r'<.*>','<H1>title</H1>').group()<H1>title</H1>>>> print re.search(r'<.*?>','<H1>title</H1>').group()<H1>>>> 
对其限定符后添加‘?’,这样就会得到非贪婪匹配或者得到最小匹配

{m}--- 刚好匹配m次,不少也不多

>>> print re.search(r'fo{3}','foooo').group()fooo>>> print re.search(r'fo{2}','foooo').group()foo>>> 

{m,n}---- 匹配正则m到n次a{3,5} will match from 3 to 5'a' characters。m缺省时表示0,n缺省时表示无限次。a{4,}b will matchaaaab or a thousand'a' characters followed by ab, but notaaab.中间的逗号不能省略。

>>> print re.search(r'a{,4}b','aaab').group()aaab>>> print re.search(r'a{4,}b','aaab').group()Traceback (most recent call last):  File "<pyshell#85>", line 1, in <module>    print re.search(r'a{4,}b','aaab').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 

{m,n}?----非贪婪模式,匹配最少的m次。For example, on the 6-character string 'aaaaaa', a{3,5} will match 5'a' characters,while a{3,5}? will only match 3 characters.

>>> print re.search(r'a{3,5}b','aaaaaab').group()aaaaab>>> print re.search(r'a{3,5}?b','aaaaaab').group()   #这种后面还有字符的情况容易出错,实际还是以n来计算的aaaaab>>> print re.search(r'a{3,5}?','aaaaaab').group()aaa>>> 

‘\' ----转义字符,用来匹配 *,?等等。不是使用raw string的情况下,Python also uses the backslash as an escape sequence in string literals;也就是不使用r'XXX时,要使用两次反斜杠才能表示一个反斜杠,用raw简单些。

>>> print re.search(r'a\*\?','aa*?b').group()a*?>>> print re.search('a\\*\\?','aa*?b').group()a*?>>> 

[ ]---存放字符集,1)中括号中的字符可以是单个的,e.g. [amk] will match'a','m', or'k'

>>> print re.search('[amk]','sdafgfhmrtykyy').group()a>>> print re.search('[amk].','sdafgfhmrtykyy').group()af>>> print re.search('[mka].','sdafgfhmrtykyy').group()af
是或关系,匹配了a,就没有再匹配 m, k。

2)也可以是一段有序字符集,for example[a-z] will match any lower case ASCII letter,[0-5][0-9] will match all the two-digits numbers from 00 to 59, and[0-9A-Fa-f] will match any hexadecimal digit. 如果'-'字符放在了字符类的开头处或末尾处,该字符就会被当作一个普通字符来看待 ,(e.g.[a\-z]) or if it’s placed as the first or last character (e.g.[a-]),it will match a literal'-'.

>>> print re.search(r'[a-z]{3}','34asdfg98dfg').group()asd
>>> print re.findall(r'[a-z]{3}','34asdfg98dfg')['asd', 'dfg']
>>> print re.findall(r'[0-5][0-9]','34asFGg38dfg')['34', '38']
[0-9a-fA-F] 匹配单个的十六进制数字,并且大小写不敏感。也可以结合范围定义与单个字符定义。[0-9a-fxA-FX] 匹配一个十六进制数字或字母X。再次强调一下,字符和范围定义的先后顺序对结果没有影响。
>>> print re.findall(r'[0-9A-Fa-f]','4A 80 7f 9z')#实际就是0-9,A-F,a-f 这一顺序数字和字符间进行匹配['4', 'A', '8', '0', '7', 'f', '9']
>>> print re.findall(r'[0-9a-fxA-FX]{3}','we2rt4fxdef8AXgh')#可以添加特定的字符x,但是def被匹配了,why?['4fx', 'def', '8AX']>>> 
>>> print re.findall(r'[a\-z]..','AXgh-erg5-6yfhka-jjhh') # a-z及其-都匹配,长度3个字符['-er', '-6y', 'a-j']>>> print re.findall(r'[a-]..','AXgh-erg5-6yfhka-jjhh')#z省略,匹配到最后['-er', '-6y', 'a-j']>>> 

3)若其中含有特殊字符,则特殊字符作为普通字符对待,For example,[(+*)] will match any of the literal characters'(','+','*', or')'.

>>> print re.findall(r'[(+*)].','AXg(df+dgf4*dfg34)fdg')['(d', '+d', '*d', ')f']

4)\w or\S也可以包含在其中,是否进行匹配主要取决于LOCALE or UNICODE mode 字符模式。

这个有单独用法

5)也可以进行反向匹配,first character of the set is'^', all the characters that are not in the set will be matched.[^5] will match any character except'5', and[^^] will match any character except'^'

>>> print re.findall(r'[5].','AXgh-erg5-6yf')['5-']>>> print re.findall(r'[^5].','AXgh-erg5-6yf') #需要与匹配字符串开头区分开['AX', 'gh', '-e', 'rg', '-6', 'yf']>>> 

6)为了匹配“] ",可以使用转义符或者放在前面,For example, both[()[\]{}] and[]()[{}] will both match a parenthesis.

>>> print re.findall(r'[()[\]{}].','AXg[h-er]g5-6y}f')['[h', ']g', '}f']>>> 

’ | ‘---- 或匹配,A|B匹配任意一个,从左往右,也可以用于分组匹配,但是一旦A匹配,B将不再进行匹配。匹配自己时, To match a literal'|', use\|, or enclose it inside acharacter class, as in[|]

>>> print re.findall(r'[5|6].','AXgh-erg5-6yf')# B还是进行了匹配['5-', '6y']>>> print re.search(r'[5|6].','AXgh-erg5-6yf').group()5->>> print re.findall(r'[5\|6].','AXgh-erg5\-6yf')['5\\', '6y']>>> >>> re.findall(r'gr(a|r)y','sfdgrayfdfggrryfgg') #与分组连用时,返回括号内匹配的内容,并没有返回整个gray 或grry,why?['a', 'r']

(...)---- 匹配圆括号中的正则表达式,表示分组的开始和结束,匹配以后分组的内容可以通过\编号来提取

1.(…) 用来匹配符合条件的字符串。并且将此部分,打包放在一起,看做成一个组,group。

2. 而此group,可以被后续(正则表达式中)匹配时所引用。

此处我称其为 前向引用,即前面已经通过group定义好的字符串,你在后面需要引用。引用的方式,是通过\N,其中N是对应的group的编号。

编号为0的group,始终代表匹配的整个字符串;编号分别对应着1,2,3,…


>>> print re.search(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg').group(1)    #没有看见\编号,但是可以用group(number)来输出gray>>> print re.search(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg').group(2)grry>>> print re.search(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg').group(3)Traceback (most recent call last):  File "<pyshell#65>", line 1, in <module>    print re.search(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg').group(3)IndexError: no such group>>> print re.findall(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg')[('gray', 'grry')]
>>> print re.findall(r'(gra.)\w+(grr.)','sfdgrayfdfggrryfgg')[('gray', 'grry')]#To match the literals'(' or')',use\( or\), or enclose them inside a character class:[(][)].>>> print re.search(r'(gr[(]a.)\w+(gr[)]r.)','sfdgr(ayfdfggr)ryfgg').group(1)gr(ay>>> print re.search(r'(gr[(]a.)\w+(gr[)]r.)','sfdgr(ayfdfggr)ryfgg').group(2)gr)ry>>> print re.search(r'(gr\(a.)\w+(gr\)r.)','sfdgr(ayfdfggr)ryfgg').group(1)gr(ay>>> print re.search(r'(gr\(a.)\w+(gr\)r.)','sfdgr(ayfdfggr)ryfgg').group(2)gr)ry>>> 

(?...) -- 扩展符号,作为扩展语法,(?P<name>...) is the only exception to this rule。匹配圆括号中的正则表达式,并创建一个指定分组。

具体如下:

(?iLmsux)----该组匹配空串,其中的每个字母代表一种匹配模式;该字符设置了对应的标志re.U (Unicode dependent),类似的有编译标志:

编译标志

编译标志让你可以修改正则表达式的一些运行方式。在 re 模块中标志可以使用两个名字,一个是全名如 IGNORECASE,一个是缩写,一字母形式如 I。(如果你熟悉 Perl 的模式修改,一字母形式使用同样的字母;例如 re.VERBOSE的缩写形式是 re.X。)多个标志可以通过按位 OR-ing 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

这有个可用标志表,对每个标志后面都有详细的说明。
标志                                                  含义
DOTALL, S                   使 . 匹配包括换行在内的所有字符
IGNORECASE, I           使匹配对大小写不敏感
LOCALE, L                   做本地化识别(locale-aware)匹配
MULTILINE, M               多行匹配,影响 ^ 和 $
VERBOSE, X                能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂

I
IGNORECASE


使匹配对大小写不敏感;字符类和字符串匹配字母时忽略大小写。举个例子,[A-Z]也可以匹配小写字母,Spam 可以匹配 "Spam", "spam", 或 "spAM"。这个小写字母并不考虑当前位置。

>>> print re.findall(r'g[a-r]{2}y','sfdgRAyfdfggRRyfgg',re.I)['gRAy', 'gRRy']>>> print re.findall(r'g[a-r]{2}y','sfdgRAyfdfggRRyfgg')[]>>> 

L
LOCALE


影响 \w, \W, \b, 和 \B,这取决于当前的本地化设置。

locales 是 C 语言库中的一项功能,是用来为需要考虑不同语言的编程提供帮助的。举个例子,如果你正在处理法文文本,你想用 \w+ 来匹配文字,但 \w 只匹配字符类 [A-Za-z];它并不能匹配 "é" 或 "ç"。如果你的系统配置适当且本地化设置为法语,那么内部的 C 函数将告诉程序 "é" 也应该被认为是一个字母。当在编译正则表达式时使用 LOCALE 标志会得到用这些 C 函数来处理 \w 后的编译对象;这会更慢,但也会象你希望的那样可以用 \w+ 来匹配法文文本。

M
MULTILINE


(此时 ^ 和 $ 不会被解释; )

使用 "^" 只匹配字符串的开始,而 $ 则只匹配字符串的结尾和直接在换行前(如果有的话)的字符串结尾。当本标志指定后, "^" 匹配字符串的开始和字符串中每行的开始。同样的, $ 元字符匹配字符串结尾和字符串中每行的结尾(直接在每个换行之前)。

>>> s = '''hello csvtcsvt hellocsvt hehe i'''>>> import re>>> re.findall(r'^csvt',s)[]>>> s'hello csvt\ncsvt hello\ncsvt hehe i\n'>>> re.findall(r'^csvt',s,re.M)['csvt', 'csvt']

S
DOTALL


使 "." 特殊字符完全匹配任何字符,包括换行;没有这个标志, "." 匹配除了换行外的任何字符。
>>> string= '''asfddfhkjkpsdjkfgfg'''>>> print re.findall(r'df.*',string,re.S)['df\nhkjkp\nsdjkfgfg\n']>>> print re.findall(r'df.*',string)['df']>>> 

X
VERBOSE


该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。当该标志被指定时,在 RE 字符串中的空白符被忽略,除非该空白符在字符类中或在反斜杠之后;这可以让你更清晰地组织和缩进 RE。它也可以允许你将注释写入 RE,这些注释会被引擎忽略;注释用 "#"号 来标识,不过该符号不能在字符串或反斜杠之后。

需要注意的是(?x) flag changes how the expression is parsed. It should be used first in the expression string, or after one or more whitespace characters.If there are non-whitespace characters before the flag, the results areundefined.

(?:...)---- (...)的不分组版本,用于使用“|” 或者后接数量词;匹配圆括号中的正则表达式,但丢弃匹配的子字符串。

>>> print re.search(r'(?:abc){2}','dfdsfabcabcfdgfg').group(1)Traceback (most recent call last):  File "<pyshell#6>", line 1, in <module>    print re.search(r'(?:abc){2}','dfdsfabcabcfdgfg').group(1)IndexError: no such group>>> print re.search(r'(abc){2}','dfdsfabcabcfdgfg').group(1)  #有分组但是没有‘?:’才正确,不存在分组abc>>> print re.search(r'(abc){2}','dfdsfabcabcfdgfg').group(2)Traceback (most recent call last):  File "<pyshell#8>", line 1, in <module>    print re.search(r'(abc){2}','dfdsfabcabcfdgfg').group(2)IndexError: no such group>>> print re.search(r'(abc){2}','dfdsfabcabcfdgfg').group(0)abcabc>>> print re.search(r'(?:abc){2}','dfdsfabcabcfdgfg').group(0)abcabc>>> print re.search(r'(?:abc){2}','dfdsfabcabcfdgfg').group()abcabc>>> 

非捕获组的目的:

只是为了,将对应的匹配的内容,弄成一个逻辑的整体,即group,但是实际上并没有记录内容为group;应该是为了,让看代码的人,更加明白所要匹配的内容的逻辑关系,并没有太多实用价值。


(?P<name>...)---- 定义一个命名组,除了原有的编号外,再指定一个额外的别名;(?P=name) 则是对命名组的逆向引用

(?P<name>…),和普通的(?…):基本类似。区别在于,此处由于是给此group命名了,所以,后续(同一正则表达式内和搜索后得到的Match对象中),都可以通过此group的名字而去引用此group。

2. group的名字,当前需要是正常的Python标识符,即字母,数字,下划线等,即,没有特殊的字符。

3.同一正则表达式内,每个group的组名,是唯一的,不能重复。

4. 虽然此处group内命名了,但是其仍然和普通的中一样,可以通过索引号,即group(1),group(2)等等,去引用对应的group的。

很明显,按照正则内被命名的group的顺序,group(1)==group(name1)

>>> print re.search(r'(?P<wo>gr.y).(?P<ni>gr.y)','sfdgrayfgrryfgg').group('wo')gray>>> print re.search(r'(?P<wo>gr.y).(?P<ni>gr.y)','sfdgrayfgrryfgg').group('ni')grry>>> >>> print re.search(r'(?P<wo>gr.y).(?P<ni>gr.y)','sfdgrayfgrryfgg').group()grayfgrry>>> print re.search(r'(?P<wo>gr.y).(?P<ni>gr.y)','sfdgrayfgrryfgg').group(1)gray>>> print re.search(r'(?P<wo>gr.y).(?P<ni>gr.y)','sfdgrayfgrryfgg').group(2)grry>>> 
Named groups can be referenced in three contexts. If the pattern is(?P<quote>['"]).*?(?P=quote) (i.e. matching a string quoted with either single or double quotes):

Context of reference to group “quote”Ways to reference itin the same pattern itself
  • (?P=quote) (as shown)
  • \1
when processing match object m
  • m.group('quote')
  • m.end('quote') (etc.)
in a string passed to the replargument of re.sub()
  • \g<quote>
  • \g<1>
  • \1


1. 一般多数是通过matched.group(name)的方式去获得对应所查找到的字符串的。

2. 关于匹配之前已经出现的字符串,可以使用:

(1)在re.search等中,使用(?P=name);

(2)在re.sub的被替换的字符串中,使用\g<name>的方式获得之前已命名的group的值;

>>> teststr='3w<a href="/tag/who are you/">who are you</a>'>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr).end('tag0')   #m.end('quote')27>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr).group('tag0') #m.group('quote')who are you>>> print re.subn(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',r'I am a student:\g<tag0>',teststr) #进行tag0替换('I am a student:who are you', 1)>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr).group()3w<a href="/tag/who are you/">who are you</a>>>> 
>>> print re.subn(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',r'I am a student:\g<1>',teststr)#不同标签替换('I am a student:who are you', 1)>>> print re.subn(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',r'I am a student:\1',teststr)('I am a student:who are you', 1)>>> 

(?P=name)---- 对命名组的逆向引用,it matches whatever text was matched by the earlier group named name.

>>> teststr='3w<a href="/tag/who are you/">who are you</a>'#已匹配的两个重复内容who are you>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag1)</a>',teststr) #引用名字要一样,都为tag0Traceback (most recent call last):  File "<pyshell#33>", line 1, in <module>    print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag1)</a>',teststr)  File "C:\Python27\lib\re.py", line 142, in search    return _compile(pattern, flags).search(string)  File "C:\Python27\lib\re.py", line 242, in _compile    raise error, v # invalid expressionerror: unknown group name>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr)<_sre.SRE_Match object at 0x01F809A0>>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr).group()3w<a href="/tag/who are you/">who are you</a>>>> print re.search(r'.+<a href="/tag/(?P<tag0>.+)/">(?P=tag0)</a>',teststr).group('tag0')#使用“P=tag0”对前一次已匹配的相同内容进行了引用who are you

1.首先,使用此(?P=name)之前,在正则表达式中,必须之前已经有了名为name的带命名的group了,即有了类似的(?P<name>)了,才可以用这个(?P=name)去匹配之前的(?P<name>)部分的值。

2.此(?p=name)只是用来匹配,即只能适用于:re.search,re.match,re.find,re.findall等,用来查询匹配的正则表达式。

而如果用于re.sub等被替换的字符中时,则是\g<name>,而不是(?P=name)。


(?#...)---- #后的内容作为注释被忽略


(?=...)----前向断言,前向匹配。括号中的’…’代表你希望匹配的字符串后面应该出现的字符串如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。模式的剩余部分还要尝试界定符的右边。Isaac(?=Asimov) will match'Isaac' only if it’s followed by'Asimov'. 和positive lookbehind assertion互相对应,此处(?=…) 的功能是:判断(当前位置)(继续向前走,向前看)后面的内容是什么。而此处的等于号,即表示去判断,后面的内容是否等于…,即去判断字符串后面的内容,是否满足一定条件,然后最终才能做出决定,判断整体上是否匹配所需要的字符串

>>> print re.search('abc(?=def)', 'abcdef').group()abc>>> print re.search('Isaac(?=Asimov)', 'IsaacAsimov').group()Isaac>>> print re.search('Isaac(?=Asimov)', 'Isaacsdfimov').group()  #不仅匹配当前Isaac,然后还要检查后面是否匹配。输出前面Traceback (most recent call last):  File "<pyshell#49>", line 1, in <module>    print re.search('Isaac(?=Asimov)', 'Isaacsdfimov').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 

lookahead assertion就是看看后面的字符串,是否也满足相应的条件。其和positive lookbehind assertion,是相对应的。

(?!...)----前向否定匹配,前向否定断言:只有当你希望的字符串后面不跟着’…’内容时才匹配前向否定界定符,与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。For example,Isaac(?!Asimov) will match'Isaac' only if it’s not followed by'Asimov'.

>>> print re.search('Isaac(?!Asimov)', 'Isaacsdfimov').group()Isaac>>> print re.search('Isaac(?!Asimov)', 'IsaacAsimov').group()Traceback (most recent call last):  File "<pyshell#51>", line 1, in <module>    print re.search('Isaac(?!Asimov)', 'IsaacAsimov').group()AttributeError: 'NoneType' object has no attribute 'group'>>> 
从当前匹配的地方,继续向前看(lookahead),然后不希望(negative)找到对应的内容

negative lookahead assertion,就是,除了正常的搜索匹配之外,继续往前走两步,继续看看,不要出现某些内容。以达到在正常匹配到的内容的基础上,过滤掉某种不想要的内容。


(?<=...)----positive lookbehind assertion。后向断言,后相匹配。括号中’…’代表你希望匹配的字符串的前面应该出现的字符串之前的字符串内容需要匹配表达式才能匹配成功。(?<=abc)def will find a match in abcdef。only match strings of some fixed length, meaning thatabc or a|b are allowed, buta* anda{3,4} are not.即字符串长度要一致。

1.一般的字符串匹配,都是匹配当前(位置开始往后)的字符串是什么。而此处的(?<=…) 的功能是,判断(当前位置)之前的内容是什么。

从此处的语法,其实也容易理解:因为其写法是 <=,即小于等于,分解为小于号和等于号:

  • 小于号:表示从当前位置往前看;
  • 等于号:表示判断前面的内容,是否为 …
作为查找字符串,在一些复杂的情况时,匹配字符串的应用中,不仅要判断当前内容是什么,还要判断当前位置之前的内容,是否满足一定条件,然后才好做出最终判断

>>> import re>>> m = re.search('(?<=abc)def', 'abcdef') #先前向匹配abc,再匹配def>>> m.group(0)'def'#This example looks for a word following a hyphen:>>>>>> m = re.search('(?<=-)\w+', 'spam-egg')#先确定‘-’匹配再取匹配的egg值>>> m.group(0)'egg'
patterns which start with positive look behind assertions will not match at the beginning of the string being searched; you will most likely want to use the search() function rather than the match() function:

(?<!...)--- negative lookbehind assertion前向非界定 :只有当你希望的字符串前面不是’…’的内容时才匹配。之前的字符串内容需要匹配表达式才能匹配成功。the contained pattern must only match strings ofsome fixed length.


(?(id/name)yes-pattern|no-pattern)---- 如果编号为id/别名为name的组匹配到字符,则匹配yes-pattern 否则匹配no-pattern。no-pattern可以省略。

此处的name或id,是针对(当前位置的)条件性匹配之前的,某个已经通过group去分组的内容

其中:

如果是有命名的分组,即named group,则对应的该分组就有对应的name,即此处所指的就是对应的name;
如果是无命名的分组,即unnamed group,则对应的该分组也有对应的分组的编号,称为group的number,也叫做id,对应的就是这里的id;

\number’通过序号调用已匹配的组,正则式中的每个组都有一个序号,序号是按组从左到右,从1开始的数字


>>> string = 'purple alice-b@google.com monkey dishwasher'
>>> string
'purple alice-b@google.com monkey dishwasher'
>>> print re.findall(r'([\w.-]+)@([\w.-]+)',string)
[('alice-b', 'google.com')]
>>> print re.search(r'([\w.-]+)@([\w.-]+)',string)
<_sre.SRE_Match object at 0x0204C848>
>>> print re.search(r'([\w.-]+)@([\w.-]+)',string).group()
alice-b@google.com
>>> print re.search(r'([\w.-]+)@([\w.-]+)',string).group(1)
alice-b
>>> print re.search(r'([\w.-]+)@([\w.-]+)',string).group(2)
google.com
>>>



可供参考的文档链接:

Python正则表达式操作指南:

http://wiki.ubuntu.org.cn/Python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97

Python正则表达式指南 :

http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

正则表达式学习心得

http://www.crifan.com/files/doc/docbook/regular_expression/release/htmls/

其它记不得了,就上面的比较重要!