3.3.1 反向引用

英文中不少单词中都有重叠出现的字母,比如shootbeep,如果希望检查某个单词是否包含重叠出现的字母,该怎么解决?

匹配字母表达式是[a-z](这里暂不考虑大写的情况)。但“重叠出现”的字母,取决于第一个[a-z]运行时的匹配结果,而不能预先设定。也就是说必须“知道”之前匹配的确切内容:如果前面匹配的是e,则后面只能是e;如果前面匹配的是a,后面就只能匹配a。

上一节讲到了引用分组,能引用某个分组内的子表达式匹配的文本,但是引用都是在匹配完成后进行的,能不能在正则表达式中引用呢?

答案是可以的,这种功能叫做反向引用(back-reference),它允许在正则表达式内部引用之前(左侧)的捕获分组匹配的文本,其形式也是\num,其中num表示所引用分组的编号,编号规则与之前介绍的相同。

根据反向引用,查找连续重叠字母的表达式就是([a-z])\1,其中的[a-z]匹配第一个字母,再用括号将匹配分组,然后用\1来反向引用。

例3-24 用反向引用匹配重复字母

print(re.search(r'([a-z])\1', 'aabb'))  # 'aa'
print(re.search(r'([a-z])\1', 'cc'))  # 'cc'
print(re.search(r'([a-z])\1', 'mn'))  # None

在日常开发中,我们经常需要反向引用来建立前后联系。最常见的就是解析html tag。在html语法中,tag包括open tagclose tag,它们经常是成对出现的,比如马小跳

title

有了反向引用,就可以先匹配open tag,再匹配其他内容,直到最近的close tag为止:用([^>]+)匹配open tagtag name,在匹配close tag时,用\1引用之前匹配的tag name

例3-25 用反向引用匹配成对的tag

pairedTagRegex = re.compile(r'<([a-zA-Z0-9]+)(\s*[^>]+)?>[\s\S]*?')

print(pairedTagRegex.search('马小跳'))  # 马小跳
print(pairedTagRegex.search('

马小跳

')) #

马小跳

print(pairedTagRegex.search('

马小跳

')) # 马小跳

反向引用还可以用在其他很多地方,比如处理中文文本时,查找“浩浩荡荡”、“明明白白”之类aabb或者“如火如荼”、“越来越好”这类abab的四字词语。

关于反向引用,还有一点需要强调:反向引用重复的是对应捕获分组匹配的文本,而不是之前的表达式;也就是说,反向引用的是由之前表达式决定的具体文本,而不是符合某种规则的未知文本

你可能感兴趣的:(3.3.1 反向引用)