标识符
先熟悉最基本的标识符
-
. : 告诉引擎匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
-
?: 告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。
-
+: 告诉引擎匹配前导字符1次或多次。
-
*: 告诉引擎匹配前导字符0次或多次。
-
{min, max}: 告诉引擎匹配前导字符min次到max次。min和max都是非负整数。如果有逗号而max被省略了,则表示max没有限制;如果逗号和max都被省略了,则表示重复min次。
表示方式:{n},{n,},{n,m},
因此 {0,} 和 * 一样,{1,} 和 + 的作用一样。
贪婪匹配:
默认情况下,? + * {min, max}都是贪婪的,也就是说,它会根据前导字符去匹配尽可能多的内容。
示例1:
import re
content = 'aacbacbc'
pattern = re.compile('a.*b')
result = re.search(pattern,content)
print(result.group())
结果:
aacbacb
例1中,匹配到第一个a后,开始匹配.*,由于是贪婪模式,
它会一直往后匹配,直到最后一个满足条件的b为止,因此匹配结果是aacbacb
示例2:
content = 'aacbacbc'
pattern = re.compile('ac.*b')
result = re.search(pattern,content)
print(result.group())
结果:
acbacb
例2中,第一个匹配的是a,然后再匹配下一个字符a时,和正则不匹配,因此匹配失败,index挪到1,接下来匹配成功了ac,继续往下匹配,由于是贪婪模式,尽可能多的去匹配结果,直到最后一个符合要求的b为止,因此匹配结果是acbacb
非贪婪匹配
正则表达式去匹配时,会尽量多的匹配符合条件的内容。
+,?,*,{n},{n,},{n,m}
匹配时,如果遇到上述标识符,代表是贪婪匹配,会尽可能多的去匹配内容。
示例1:
content = 'aacbacbc'
pattern = re.compile('a.*?b')
result = re.search(pattern,content)
print(result.group())
结果:
aacb
上例中,匹配到第一个a后,开始匹配.*?,由于是非贪婪模式,它在匹配到了第一个b后,就匹配成功了,因此匹配结果是aacb
为什么是aacb而不是acb呢? 因为前面有提到过一个正在匹配的优先规则: 最先开始的匹配拥有最高的优先权 第一个a匹配到了,只要之后没有发生匹配失败的情况,它就会一直匹配下去,直到匹配成功。
示例2:
content = 'aacbacdbc'
pattern = re.compile('ac.*?b')
result = re.findall(pattern,content)
print(result)
结果:
[‘acb’, ‘acdb’]
上例中没用re.search,因为它返回第一个成功的匹配结果,我们用re.findall,找出所有符合匹配的结果。
示例3:
content = 'aacbacbc'
pattern1 = re.compile('a.*?')
result1 = re.search(pattern1,content)
print(result1.group())
pattern2 = re.compile('a.*')
result2 = re.search(pattern2,content)
print(result2.group())
结果:
a
aacbacbc
这一个例子则是对非贪婪匹配示例1的补充,可以发现,当后面没有b时,由于是非贪婪模式,匹配到第一个a就直接匹配成功了 而后面一个贪婪模式的匹配则是会匹配所有。