【卷一】正则表达式二

正则表达式一般是爬虫用的,下面我们就通过一题多解来学习下正则表达式

参考:《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 种形式

 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()显示的东西,再看一下下面的例子,就清楚了

 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带减号的进程名,个人感觉方法一比较顺手!!

 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+元素

就行了。

类似的错误还有(~| )+ 和 (~|.)+

posted @ 2016-08-21 14:45  坏小孩D_R  阅读(180)  评论(0编辑  收藏  举报