python之re模块(正则表达式)分组、断⾔详解提⽰:阅读本⽂需要有⼀定的正则表达式基础。
正则表达式中的断⾔,作为⾼级应⽤出现,倒不是因为它有多难,⽽是概念⽐较抽象,不容易理解⽽已,今天就让⼩菜通俗的讲解⼀下。
如果不⽤断⾔,以往⽤过的那些表达式,仅仅能获取到有规律的字符串,⽽不能获取⽆规律的字符串。
举个例⼦,⽐如html源码中有<title>xxx</title>标签,⽤以前的知识,我们只能确定源码中的<title>和</title>是固定不变的。因此,如果想获取页⾯标题(xxx),充其量只能写⼀个类似于这样的表达式:<title>.*</title>,⽽这样写匹配出来的是完整的<title>xxx</title>标签,并不是单纯的页⾯标题xxx。
想解决以上问题,就要⽤到断⾔知识。
在讲断⾔之前,读者应该先了解分组,这有助于理解断⾔。
分组在正则中⽤()表⽰,根据⼩菜理解,分组的作⽤有两个:
n  将某些规律看成是⼀组,然后进⾏组级别的重复,可以得到意想不到的效果。
n  分组之后,可以通过后向引⽤简化表达式。
先来看第⼀个作⽤,对于IP地址的匹配,简单的可以写为如下形式:
\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}
但仔细观察,我们可以发现⼀定的规律,可以把.\d{1,3}看成⼀个整体,也就是把他们看成⼀组,再把这个组重复3次即可。表达式如下:
\d{1,3}(.\d{1,3}){3}
这样⼀看,就⽐较简洁了。
再来看第⼆个作⽤,就拿匹配<title>xxx</title>标签来说,简单的正则可以这样写:
<title>.*</title>
可以看出,上边表达式中有两个title,完全⼀样,其实可以通过分组简写。表达式如下:
<(title)>.*</\1>
这个例⼦实际上就是反向引⽤的实际应⽤。对于分组⽽⾔,整个表达式永远算作第0组,在本例中,第0组是<(title)>.*</\1>,然后从左到右,依次为分组编号,因此,(title)是第1组。
⽤\1这种语法,可以引⽤某组的⽂本内容,\1当然就是引⽤第1组的⽂本内容了,这样⼀来,就可以简化正则表达式,只写⼀次title,把它放在组⾥,然后在后边引⽤即可。
以此为启发,我们可不可以简化刚刚的IP地址正则表达式呢?原来的表达式为\d{1,3}(.\d{1,3}){3},⾥边的\d{1,3}重复了两次,如果利⽤后向引⽤简化,表达式如下:
(\d{1,3})(.\1){3}
简单的解释下,把\d{1,3}放在⼀组⾥,表⽰为(\d{1,3}),它是第1组,(.\1)是第2组,在第2组⾥通过\1语法,后向引⽤了第1组的⽂本内容。
经过实际测试,会发现这样写是错误的,为什么呢?
⼩菜⼀直在强调,后向引⽤,引⽤的仅仅是⽂本内容,⽽不是正则表达式!
也就是说,组中的内容⼀旦匹配成功,后向引⽤,引⽤的就是匹配成功后的内容,引⽤的是结果,⽽不是表达式。
因此,(\d{1,3})(.\1){3}这个表达式实际上匹配的是四个数都相同的IP地址,⽐如:123.123.123.123。
⾄此,读者已经掌握了传说中的后向引⽤,就这么简单。
接下来说说什么是断⾔。
所谓断⾔,就是指明某个字符串前边或者后边,将会出现满⾜某种规律的字符串。
就拿⽂章开篇的例⼦来说,我们想要的是xxx,它没有规律,但是它前边肯定会有<title>,后边肯定会有</title>,这就⾜够了。想指定xxx前肯定会出现<title>,就⽤正后发断⾔,表达式:(?<=<title>).*
向指定xxx后边肯定会出现</title>,就⽤正先⾏断⾔,表达式:.*(?=</title>)
两个加在⼀起,就是(?<=<title>).*(?=</title>)
这样就能匹配到xxx。
相信读者看到这,已经蒙了,不⽤急,待⼩菜慢慢讲来。
其实掌握了规律,就很简单了,⽆论是先⾏还是后发,都是相对于xxx⽽⾔的,也就是相对于⽬标字符串⽽⾔。
假如⽬标字符串后边有条件,可以理解为⽬标字符串在前,就⽤先⾏断⾔,放在⽬标字符串之后。
假如⽬标字符串前边有条件,可以理解为⽬标字符串在后,就⽤后发断⾔,放在⽬标字符串之前。
假如指定满⾜某个条件,就是正。
假如指定不满⾜某个条件,就是负。
断⾔只是条件,帮你到真正需要的字符串,本⾝并不会匹配!
(?=X )零宽度正先⾏断⾔。仅当⼦表达式 X 在此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,⽽不与该数字匹配。此构造不会回溯。
(?!X)零宽度负先⾏断⾔。仅当⼦表达式 X 不在此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配,⽽不与该数字匹配。
(? <=X)零宽度正后发断⾔。仅当⼦表达式 X 在此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后⾯的 99 的实例匹配。此构造不会回溯。
python正则表达式判断(?
<!X)零宽度负后发断⾔。仅当⼦表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后⾯的 99 的实例匹配从断⾔的表达形式可以看出,它⽤的就是分组符号,只不过开头都加了⼀个问号,这个问号就是在说这是⼀个⾮捕获组,这个组没有编
号,不能⽤来后向引⽤,只能当做断⾔。
教程到此结束,希望⼤家阅读愉快!