【卷一】正则表达式二
正则表达式一般是爬虫用的,下面我们就通过一题多解来学习下正则表达式
参考:《Python核心编程(3rd)》—P33
. : 句点或者说点号,匹配任意字符,但不包括换行符 '\n'
+ : 匹配前面的字符1次或多次
\w: 匹配1个字母或数字,
\w+: 匹配一个单词或多个字母,数字等
\d : 匹配1个数字, \d+: 匹配多个数字
\s : 匹配1个空格, \s+: 匹配多个空格,
\s\s+: 至少匹配2个空格
a|b: 管道符号,匹配a或者b, 也叫择一匹配
[A-Za-z]: 匹配A-Z和a-z的任一个字母
下面是我们要分割的内容,先把字符串data按照行分割成列表
1 # coding: utf-8 2 3 import re 4 5 data = """ 6 System 4 Services 0 388 K 7 smss.exe 408 Services 0 1,440 K 8 System Idle Process 0 Services 0 24 K 9 """ 10 11 data = data.split("\n")
这是我们要得到的结果,下面列出几种正则表达式的写法
[('System ', '4', '388 K')]
[('smss.exe ', '408', '1,440 K')]
[('System Idle Process ', '0', '24 K')]
方法一:
这种方法缺点是无法去除元组第一个元素后面的空格,但因句点 '.' 可匹配
除'\n' 外的任何字符,故可匹配像 'vmware-hostd.exe' 这样的进程
推荐第 3 种形式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 把上面的代码copy下来 2 3 for i in data: 4 # (?: )与 '|' 5 print re.findall(r"((?:\w+.)+)\s\s+(\d+) \w+\s\s+\d\s\s+(\d+ K|\d+,\d+ K)", i) 6 # (?: )与 '(?:|)' 7 #print re.findall(r"((?:\w+.)+)\s\s+(\d+) \w+\s\s+\d\s\s+((?:\d+|\d+,\d+) K)", i) 8 # (?: )与 '[]' 9 #print re.findall(r"((?:\w+.)+)\s\s+(\d+) \w+\s\s+\d\s\s+([\d+,]+ K)", i) 10 11
结果如下:
注意,((?:\w+.)+)写成((?:\w.)+)也可以输出,问题是有些进程名称像smss.exe
会变成 'mss.exe',因为只有点号 '.' 能匹配点,所以为了能匹配成功,只能 \w.\w.
这样匹配
(?: )是不保存匹配的分组,一般我们用括号圈起来的内容就是我们要的数据,
也就是findall()显示的东西,再看一下下面的例子,就清楚了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # coding: utf-8 2 3 import re 4 5 d = "System Idle Process 0 Services 0 24 K" 6 7 # 我们要的是System到Process,0到Service的部分,而(\w+.)只是((\w+.)+)匹配的字符的末尾,也就是 8 # 'Process ', 'Service'等等, ((\w+.)+)其实是两个子组(可以简单理解为用括号圈起来的就是子组) 9 print re.findall(r"((\w+.)+)", d) 10 print "-" * 40 11 print re.findall(r"(\w+.)+", d) 12 print "-" * 40 13 print re.findall(r"((?:\w+.)+)", d)
-----------------------------------------------------------------------------------------------------------
方法2:
优点是去除了元组第一个元素后面的空格,但由于句点 '.' 在[ ]内只能匹配其本身'.',
所以无法匹配像vmware-hostd.exe带减号的进程名,个人感觉方法一比较顺手!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # coding: utf-8 2 3 import re 4 5 data = """ 6 System 4 Services 0 388 K 7 smss.exe 408 Services 0 1,440 K 8 System Idle Process 0 Services 0 24 K 9 """ 10 11 data = data.split("\n") 12 13 for i in data: 14 # '*'是匹配前面的字符0次或1次,注意这里不能用'+'替代,比如System并没有后面的单词 15 print re.findall(r"([\w.]+(?: \w+)*)\s\s+(\d+) \w+\s\s+\d+\s\s+([\d,]+ K)", i)
当有多重括号时,要根据需要的内容看是否保留分组,从而判断是否加 (?: )
注意:
'[]' 里的句点 '.' 和 '+' 只是表示普通的符号,并没有其他作用 !!!
这里容易出错的是把'[\w.]+' 写成'[\w+. ]'加空格的形式,'(\w|.)+' 也是比较容易错的写法,
因为+是匹配前的字符1或任意次,这两种写法都会导致元组第一个元素匹配多个空白字符,因
为\s\s+只是至少匹配2个空格,意味着前面匹配完后最多只要留下2个空格给后面的\s\s+元素
就行了。
类似的错误还有(~| )+ 和 (~|.)+