注:文章原文为Dr. Charles Severance 的 《Python for Informatics》。文中代码用3.4版改写,并在本机测试通过。

11.2 用正则表达式抽取数据

  在Python中,我们可以使用findall()方法从字符串中抽取所有匹配正则表达式的子字符串。接下来我们会用一个例子,从行中抽取看起来像电子邮件地址的字符串,而不考虑行的格式。比如,我们想从下面几行字符串中拉出电子邮件地址。

From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008
Return-Path: <postmaster@collab.sakaiproject.org>
for <source@collab.sakaiproject.org>;
Received: (from apache@localhost)
Author: stephen.marquard@uct.ac.za

  但我们又不想为每一行编写不同的代码来分离、切片字符串。下面的程序用findall()找到包含电子邮件地址的行,然后从每一行中抽取一个或者更多的地址。

 import re
s = 'Hello from csev@umich.edu to cwen@iupui.edu about the meeting @2PM'
lst = re.findall('\S+@\S+', s)
print(lst)

  findall()方法查找它的第二参数s并返回所有类似电子邮件地址的字符串。这里我们用了两个字符序列"\S"来匹配非空白字符。其输出将会是:

['csev@umich.edu', 'cwen@iupui.edu']

  这个正则表达式表明我们正在查找这样一个字符串:由一个以上非空白字符开头,紧跟着@符,然后再跟着一个以上非空白字符的字符串。而且,“\S"表达式将匹配所有的非空字符(这在正则表达式中被叫做”贪婪的“)。

  这个正则表达式将两次匹配到符合要求的字符串(cesv@umich.edu 和 cwen@iupui.edu),但它不会匹配”@2PM“,因为这个字符串的@符之前没有非空白字符。我们可以在程序中利用这个正则表达式读取文件的所有行,并打印出任何看起来像电子邮件地址的字符串:

 import re
hand = open('mbox-short.txt')
for line in hand:
line = line.rstrip()
x = re.findall('\S+@\S+', line)
if len(x) > 0 :
print(x)

  我们读取每一行,然后抽取所有匹配这个正则表达式的字符串。因为findall()返回的是一个列表,所以我们只要检查这个列表的元素个数是否大于零就可判断并打印出至少一个以上的邮件地址。如果我们运行这个程序,将会得到以下输出:

['wagnermr@iupui.edu']
['cwen@iupui.edu']
['<postmaster@collab.sakaiproject.org>']
['<200801032122.m03LMFo4005148@nakamura.uits.iupui.edu>']
['<source@collab.sakaiproject.org>;']
['<source@collab.sakaiproject.org>;']
['<source@collab.sakaiproject.org>;']
['apache@localhost)']
['source@collab.sakaiproject.org;']

  输出的有些电子邮件地址的开头或结尾有一些不正确的字符像"<"或";"。而我们声明只对以字母或数字开头,以字母结尾的字符串感兴趣。

  为做到这一点,我们使用另一特性的正则表达式。方括号被用来表示多个可接受字符的集合。在一定程度上,"\S"是要求匹配非空白字符,现在我们需要更加清楚的匹配规则。

  下面是我们新的正则表达式:

[a-zA-Z0-9]\S*@\S*[a-zA-Z]

  这个表达式变得有点复杂,这让你明白为什么对正则表达式而言,它拥有自己的语言。这个表达式表示我们要找的字符串是这样的:以字母(大小写均可)或数字开头的,接着是任意个非空白字符,可以是零个,中间是@符,接下来又是非空白字符,最后是字母结尾。其中[a-z]和[A-Z]分别表示26个大小写字母,[0-9]表示10个数字,"\S*"表示任意个非空白字符。这里用星号代替加号,是因为方括号内已有一个字符。记住,星号和加号只应用于其紧邻的左侧字符。

  如果我们在程序中使用这个正则表达式,我们获得的数据将更加干净:

 import re
hand = open('mbox-short.txt')
for line in hand:
line = line.rstrip()
x = re.findall('[a-zA-Z0-9]\S*@\S*[a-zA-Z', line)
if len(x) > 0 :
print(x)

['wagnermr@iupui.edu']
['cwen@iupui.edu']
['postmaster@collab.sakaiproject.org']
['200801032122.m03LMFo4005148@nakamura.uits.iupui.edu']
['source@collab.sakaiproject.org']
['source@collab.sakaiproject.org']
['source@collab.sakaiproject.org']
['apache@localhost']

  请注意“source@collab.sakaiproject.org”这几行,我们的新表达式消除了其尾部的">;"两个字符。这是因为我们的表达式添加[a-zA-Z]后,要求正则表达式的解析器找到的字符串必须以字母结尾,所以它就简单的停在了"g"上,而剔除了">;"。

  同时需要注意的是,程序输出的是Python的列表,列表中的每个元素都是字符串。

  

Python for Informatics 第11章 正则表达式三(译)的更多相关文章

  1. Python for Informatics 第11章 正则表达式五(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.4 转义字符 之前我们在正 ...

  2. Python for Informatics 第11章 正则表达式六(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.7 调试 Python有一 ...

  3. Python for Informatics 第11章 正则表达式四(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.3 组合查询和抽取 如果我 ...

  4. Python for Informatics 第11章 正则表达式二(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.1 正则表达式的字符匹配 ...

  5. Python for Informatics 第11章 正则表达式一(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 目前为止,我们一直在通读文件,查 ...

  6. 《Python学习手册 第五版》 -第11章 赋值、表达式和打印

    上一章对Python的语句和语法已经进行了基本的说明,接下来就是每个章节的详细说明,本章的主要内容就是标题中涵盖的三点:赋值语句.表达式语句.打印语句 本章重点内容如下: 1.赋值语句 1)赋值语句的 ...

  7. 路飞学城—Python爬虫实战密训班 第三章

    路飞学城—Python爬虫实战密训班 第三章 一.scrapy-redis插件实现简单分布式爬虫 scrapy-redis插件用于将scrapy和redis结合实现简单分布式爬虫: - 定义调度器 - ...

  8. Python for Infomatics 第12章 网络编程三(译)

    注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 12.5 HTML分析和网页抓取 ...

  9. python中关于正则表达式三

    2015年8月14日 11:10 7.2正则表达式操作 正则表达式使用反斜杠字符'\'来暗示一些特殊的形式或者允许特殊的字符使用但是没有调用它们特殊的意思.在字符串常量中的相同目标的字符的python ...

随机推荐

  1. JAVA作业 字符变整型相加,整型输出

    从命令行接收多个数字求和输出 一.设计思想 用输入语句输入两个字符串,分别转化成整型Integer.parseInt(string),相加,将结果再转化为字符串型String.valueOf(int) ...

  2. JS 获取浏览器窗口大小

    JS 获取浏览器窗口大小 <script> // 获取窗口宽度 if (windows.innerWidth) { winWidth = windows.innerWidth; } els ...

  3. JavaScript的内置对象和浏览器对象

    在javascript中对象通常包括两种类型:内置对象和浏览器对象,此外,用户还可以自定义对象. 对象包含两个要素:1.用来描述对象特性的一组数据,也就是若干变量,通常称为属性.2.用来操作对象特性的 ...

  4. 那些年,我们在Django web开发中踩过的坑(一)——神奇的‘/’与ajax+iframe上传

    一.上传图片并在前端展示 为了避免前端整体刷新,我们采用ajax+iframe(兼容所有浏览器)上传,这样用户上传之后就可以立即看到图片: 上传前: 上传后: 前端部分html: <form s ...

  5. c++ 的 static_cast

    http://www.cnblogs.com/pigerhan/archive/2013/02/26/2933590.html #include "Person.h" #inclu ...

  6. Getting Started with Blocks

    本文来源为:developer.apple.com,仅仅是博主练习排版所用. Getting Started with Blocks The following sections help you t ...

  7. C# 令某个窗体可跟着鼠标移动

    /// <summary> /// 使窗口的中的指定控件支持运行时移动 /// TODO:运行时缩放 /// </summary> public class ControlMo ...

  8. C# RFID windows 服务 串口方式

    话说RFID以前很火所以整理一下一年前自己处理的RFID程序,放源码. 一开始觉得他是个很神奇的东西. 包含串口通讯和网络通讯. 由于网络通讯设备太贵,所以国内的设备基本上都是在外置一个比较便宜的模块 ...

  9. Android JNI开发生成.h头文件问题(转)

    在JNI开发中,首先要将建立的anroid类编译成.h文件,编译用到命令javah,由于第一次用,以前对java的编译过程也不怎么了解,所以走了好多弯路,网络没有对这一步的详细介绍,这里讲一下: 通过 ...

  10. 制作U盘启动系统盘

    下载ULtraISO,安装之后,先打开一个iso系统文件,然后选中菜单“启动”下的“写入硬盘映像”