Python 正则表达式入门(中级篇)#
初级篇连接:http://www.cnblogs.com/chuxiuhong/p/5885073.htmlhtml
上一篇咱们说在这一篇里,咱们会介绍子表达式,向前向后查找,回溯引用。到这一篇开始前除了回溯引用在一些场合不可替代之外,大部分状况下的正则表达式你应该都会写了。python
1.子表达式##
子表达式的概念特别好理解。其实它就是将几个字符的组合形式看作一个大的“字符”。很差理解?举个栗子:咱们要匹配相似IP地址这种形式的字符(暂且不考虑数值范围的合理性,这个留做学完以后的思考题吧)。形如192.168.1.1这样的地址咱们怎么写表达式呢?正则表达式
答案一 \d+.?\d+.?\d+.?\d+
很差,一个是太繁琐,另外一个是连位数都控制不了url
答案二 \d+{1,3}.?\d+{1,3}.?\d+{1,3}.?\d+{1,3}
通常般,复杂可是起码能把位数控制在合理范围spa
答案三 (\d+{1,3}\.){3}\d+{1,3}\.
利用子表达式,将123.
这种数字加小数点看作一个总体字符,对其规定重复匹配的次数,既简洁,效果又好。因此只要你将几个字符组合用圆括号括起来,那么你就能够把一个圆括号内的内容当作一个字符,外面能够加咱们以前讲过的全部元字符来控制匹配。.net
2.向前向后查找##
如今,咱们终于来到了向前向后查找这一块。为何说终于来到这了呢?还记得咱们在初级篇最开始的例子吗?code
假如你在写一个爬虫,你获得了一个网页的HTML源码。其中有一段html <html><body><h1>hello world</h1></body></html> 你想要把这个hello world提取出来 import re key = r"<html><body><h1>hello world</h1></body></html>"#这段是你要匹配的文本 p1 = r"(?<=<h1>).+?(?=</h1>)"#这是咱们写的正则表达式规则,你如今能够不理解啥意思 pattern1 = re.compile(p1)#咱们在编译这段正则表达式 matcher1 = re.search(pattern1,key)#在源文本中搜索符合正则表达式的部分 print matcher1.group(0)#打印出来
这个正则表达式htm
p1 = r"(?<=<h1>).+?(?=<h1>)"
看到(?<=<h1>)
和 (?=<h1>)
了吗?第一个?<=表示在被匹配字符前必须得有<h1>
,后面的?=表示被匹配字符后必须有<h1>
blog
简单来讲,就是你要匹配的字符是XX,但必须知足形式是AXXB这样的字符串,那么你就能够这样写正则表达式字符串
p = r"(?<=A)XX(?=B)"
匹配到的字符串就是XX。而且,向前查找向后查找不须要必须同时出现。若是你愿意,能够只写知足一个条件。
因此你也不须要记住哪一个是向前查找,哪一个是向后查找。只要记住?<=后面跟着的是前缀要求,?=后面跟的是后缀要求。
本质上来讲,向前查找和向后查找实际上是匹配整个字符串,即AXXB,但返回时仅仅返回一个XX。也就是说,若是你愿意,彻底能够避开向前向后查找的方式,直接匹配带有先后缀的字符串,而后作字符串切片处理。
3.回溯引用##
不一样于前面的向前向后查找,这一条有时候你未必绕的过去。在有些状况下,你还必须得用到回溯引用,因此你若是想拥有在实际应用中使用正则表达式,回溯引用是你应该了解和掌握的。
咱们仍是从最开始的例子来讲。
你本来要匹配<h1></h1>
之间的内容,如今你知道HTML有多级标题,你想把每一级的标题内容都提取出来。你也许会这样写:
p = r"<h[1-6]>.*?</h[1-6]>"
这样一来,你就能够将HTML页面内全部的标题内容所有匹配出来。即<h1></h1>
到<h6></h6>
的内容均可以被提取出来。可是咱们以前说过,写正则表达式困难的不是匹配到想要的内容,而是尽量的不匹配到不想要的内容。在这个例子中,颇有可能你就会被下面这样的用例玩坏。
比方说
<h1>hello world</h3>
发现后面的</h3>
了吗?咱们不论是怎么写出来这样的标题的,但实实在在的是咱们的正则表达式一样会把这里面的hello world匹配出来。这时候就是回溯引用的重要做用。下面就是一个示例:
import re key = r"<h1>hello world</h3>" p1 = r"<h([1-6])>.*?</h\1>" pattern1 = re.compile(p1) m1 = re.search(pattern1,key) print m1.group(0)#这里是会报错的,由于匹配不到,你若是将源字符串改为</h1> 结尾就能看出效果
看到\1
了吗?本来那个位置应该是[1-6]
,可是咱们写的是\1,咱们以前说过,转义符\
干的活就是把特殊的字符转成通常的字符,把通常的字符转成特殊字符。普普统统的数字1被转移成什么了呢?在这里1表示第一个子表达式,也就是说,它是动态的,是随着前面第一个子表达式的匹配到的东西而变化的。比方说前面的子表达式内是[1-6]
,在实际字符串中找到了1,那么后面的\1就是1,若是前面的子表达式在实际字符串中找到了2,那么后面的\1就是2。
相似的,\2,\3,....就表明第二个第三个子表达式。
因此回溯引用是正则表达式内的一个“动态”的正则表达式,让你根据实际的状况变化进行匹配。
中级篇就到这里,其实正则表达式还有不少细节尚未写出来,也有不少元字符我没有交代,但掌握了纲要,懂得原理以后剩下的就相似于查表构造这种活了。
建议看到这的朋友看看《正则表达式必知必会》,初级篇和这篇中有几个例子也是取材于此。