一、分组功能
括号作用于几个字符的话,就说明这几个字符是一个整体,比如(ab)+就匹配ab作为一个整体出现的情况
例如:

print re.search(r"^ab+$", "abb") != None # =>True 

 print re.search(r"^ab+$", "abab") != None # =>False 

 print re.search(r"^(ab)+$", "abb") != None # =>False 

 print re.search(r"^(ab)+$", "abab") != None # =>True


一种常见的用法就是要匹配m或者n个字符的时候,就可以用分组来实现:\d{13,16}表示13-16个数字,如果要表示13或者16个数字的时候就可以用 \d{13}(\d{3})?

二、多选结构
多选结构的形式: "|"
比如要匹配IP地址一个字段:([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])
注意:^ab|cd$ 表示的是(^ab|cd$),指字符串开头的ab或者字符串结尾的cd,要表示只包含ab或者cd的字符串需要用^(ab|cd)$

三、引用分组
使用括号之后,正则表达式会保存每个分组真正匹配的文本,等到匹配完之后,通过group(num)之类的方法引用分组在匹配时获取的内容。
例如:表示日期字符串:2010-12-22,匹配表达式为(\d{4})-(\d{2})-(\d{2})

print re.search(r"(\d{4})-(\d{2})-(\d{2})", "2012-12-22").group(1) # =>2012 

 print re.search(r"(\d{4})-(\d{2})-(\d{2})", "2012-12-22").group(2) # =>12 

 print re.search(r"(\d{4})-(\d{2})-(\d{2})", "2012-12-22").group(1) # =>22 

 print re.search(r"(\d{4})-(\d{2})-(\d{2})", "2012-12-22").group(0) 

 # =>2012-12-22 (编号为0的分组对应整个表达式匹配的文本)



对于嵌套的括号,分组的编号是根据开括号出现的顺序来计数的, 例如:
(((\d{4})-(\d{2}))-(\d{2})),编号为0和编号为1的分组对应2012-12-22,编号为2的分组对应2012-12,编号为3的分组对应2012,编号为4的分组对应12,编号为5的分组对应22

python语言中进行正则表达式的替换方法是re.sub(pattern, replacement, string),其中pattern是用来匹配被替换文本的表达式,replacement是要替换成的文本,string是要进行替换操作的字符串,比如re.sub(r"[a-z]", " ", string)就是将string中的小写字母替换成空格,例如:
print re.sub(r"[a-z]", " ", "1a2b3c") # =>1 2 3

在replacement中也可以引用分组,形式是\num,num是对应分组的编号
例如:
print re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\2/\3/\1", "2012-12-22")
# =>12/22/2010 (其中r"\2/\3/\1" 也可用用"\\2/\\3/\\1"替换)
值得注意的是此处不能用\0,因为\0已经被用作八进制形式表示的字符,如果需要取相同的值得话,可以先用括号把整个表达式加上一对括号,之后用\1来引用

四、反向引用
如果希望检查某个单词是否包含重叠出现的字母,就需要用到反向引用,反向引用就是在正则表达式内部引用之前捕获分组匹配的文本,例如([a-z])\1匹配连续重叠字母的表达式
例如:

print re.search(r"^([a-z])\1\1$", "aa") != None # =>True 


 pairedTagRegex = r"<([^>]+)>[\s\S]*?</\1>" 

 print re.search(pairedTagRegex, "<bold>text</bold>") != None # =>True 


 pairedTagRegex = r"<([a-zA-Z0-9]+)(\s[^>]+)?>[\s\S]*?</\1>" 

 print re.search(pairedTagRegex, "<span class=\"class1\">text</span>") != None 

 # =>True



注意:python中\10表示第10个编号的分组,所以如果要表示第一个编号的分组加上0的话就可以使用\g<1>0这种方式,这样可以避免二义性

五、命名分组
又有用数字编号来表示分组不够直观,并且括号多了之后容易混淆,所以一些语言和工具又提供了命名分组,在Python中用(?P<name>)来分组,再用group(name)来获得对应分组匹配的文本
例如:

namedRegex = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})" 

 result = re.search(namedRegex, "2012-12-22") 

 print result.group("year") # =>2012 

 print result.group("month") # =>12 

 print result.group("day") # =>22 

 print result.group(1) # =>2012



六、非捕获分组
用非捕获分组修饰的表达式,在引用分组的时候会略过,非捕获表达式的形式为:(?:\d{4})

七、括号的转义
()|这三个符号在转义的时候都必须转义,不能只转义一个比如"^\(a\|b\)$"