《Python核心编程(第3版)》——1.4 一些正则表达式示例

1.4 一些正则表达式示例

下面看一些Python正则表达式的示例代码,这将使我们更接近实际应用中的程序。如下所示,以POSIX(UNIX风格操作系统,如Linux、Mac OS X等)的who命令的输出为例,该命令将列出所有登录当前系统中的用户信息。

$ who
wesley    console   Jun 20 20:33
wesley    pts/9    Jun 22 01:38  (192.168.0.6)
wesley    pts/1    Jun 20 20:33  (:0.0)
wesley    pts/2    Jun 20 20:33  (:0.0)
wesley    pts/4    Jun 20 20:33  (:0.0)
wesley    pts/3    Jun 20 20:33  (:0.0)
wesley    pts/5    Jun 20 20:33  (:0.0)
wesley    pts/6    Jun 20 20:33  (:0.0)
wesley    pts/7    Jun 20 20:33  (:0.0)
wesley    pts/8    Jun 20 20:33  (:0.0)

可能我们想要保存一些用户登录信息,诸如登录名、用户登录的终端类型、用户登录的时间和地点。在前面的示例中使用str.split()方法并不高效,因为此处的空白符既不稳定也不一致。另一个问题是在登录时间戳中间的月、日和时间之间有空格,我们可能想要保存这些连续的字段。

读者需要一些方法描述诸如“分割两个或者多个空白符”之类的模式。这通过正则表达式很容易完成。很快,我们可以使用正则表达式模式ss+,该模式的意思是至少拥有两个以上的空白符。

下面创建一个名为rewho.py的程序,该程序读取who命令的输出,然后假定将得到的输出信息存入一个名为whoadat.txt的文件之中。rewho.py脚本最初如下所示:

import re
f = open('whodata.txt', 'r')
for eachLine in f:
print re.split(r'\s\s+', eachLine)
f.close()

上述代码同样使用原始字符串(将字母“r”或者“R”放置在左引号之前),主要目的是为了避免转义特殊字符串字符,如n,该字符并不是特殊的正则表达式模式。对于确实拥有反斜线的正则表达式模式,读者可能希望逐字地处理它们;否则,读者必须在前面加上双斜线来保持它们的安全。

现在将执行who命令,保存输出到whodata.txt文件之中,然后调用rewho.py查看结果。

$ who > whodata.txt
$ rewho.py
['wesley', 'console', 'Jun 20 20:33\012']
['wesley', 'pts/9', 'Jun 22 01:38\011(192.168.0.6)\012']
['wesley', 'pts/1', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/2', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/4', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/3', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/5', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/6', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/7', 'Jun 20 20:33\011(:0.0)\012']
['wesley', 'pts/8', 'Jun 20 20:33\011(:0.0)\012']

这是非常好的一次尝试。首先,我们不期望单个制表符(ASCII 011)作为输出的一部分(可能看起来像是至少两个空白符),然后可能我们并不真的希望保存n(ASCII 012)作为每一行的终止符。我们现在将修复这些问题,然后通过一些改进来提高应用的整体 质量。

首先,应当在脚本内部运行who命令而不是在外部,然后将输出存入whodata.txt文件,如果手动重复做这件事很快就会感到厌倦。要在该程序中调用其他程序,需要调用os.popen()命令。尽管os.popen()命令现在已经被subprocess模块所替换,但它更容易使用,而且此处的重点是展示re.split()的功能。

去除尾部的n(使用str.rstrip()),然后添加单个制表符的检查,用于代替re.split()分隔符。示例1-1展示最终的rewho.py脚本在Python 2中的版本。

示例1-1 分割POSIX的who命令输出(rewho.py)

该脚本调用who命令,然后通过不同类型的空白字符分割输入的数据解析输入。

示例1-2 rewho.py脚本的Python 3版本(rewho3.py)

该rewho.py的Python 3版本仅简单地运用print()函数替换了print语句。当使用with语句(从Python 2.5版本起可用)时,记住,file(Python 2)或者io(Python 3)对象的上下文管理器会自动调用f.close()。

通过使用with语句,拥有上下文管理器的对象变得更易于使用。关于with语句和上下文管理的更多信息,请参考Core Python Pragramming或者Core Pythom Language Fundamentals中的“Errors and Exceptions”章节。记住,两个版本(rewho.py或者rewho3.py)中的who命令仅能在POSIX系统中使用,除非可以在Windows系统的计算机中使用Cygwin。对于运行Microsoft Windows的个人电脑,可以尝试tasklist命令,但读者还需要做一个额外的调整。继续阅读本章后续的章节,查看一个执行that命令的示例。

示例1-3将rewho.py和rewho3.py合并为rewhoU.py,该名称的含义是“通用的rewho”。该程序能够在Python 2和3的解释器下运行。我们欺骗并避免使用print或者print(),方法是使用一个在2.x和3.x版本中都存在并且功能并不齐全的函数:distutils.log.warn()。这是一个单字符串输出函数,因此如果输出要复杂一些,就需要合并所有输出到一个字符串中,然后调用。要在该脚本中指明它的使用方式,就将它命名为printf()。

我们也在此使用with语句。这就意味着读者需要至少使用Python 2.6版本来运行该程序。这还不确切。之前提到过,在2.5版本中with语句是试验性的。这就意味着如果想要在Python 2.5中使用,就需要导入额外的语句:from __future__ import with_statement。如果读者仍在使用2.4或者更老的版本,就不能使用这个import语句,并且必须按照示例1-1那样运行这段代码。

示例1-3 rewho.py脚本的通用版本(rewhoU.py)

该脚本运行在Python 2 和 3 下,通过一个很简单的替换来代替print语句和print()函数。该脚本还包含从Python 2.5开始引入的with语句。

rewhoU.py的创建是一个介绍如何创建通用脚本的示例,这将帮助我们避免为Python 2和3同时维护两个版本的相同脚本。

使用合适的解释器执行这些脚本中的任何一个都会得到正确、简洁的输出。

$ rewho.py
['wesley', 'console', 'Feb 22 14:12']
['wesley', 'ttys000', 'Feb 22 14:18']
['wesley', 'ttys001', 'Feb 22 14:49']
['wesley', 'ttys002', 'Feb 25 00:13', '(192.168.0.20)']
['wesley', 'ttys003', 'Feb 24 23:49', '(192.168.0.20)']

同样不要忘记,之前的小节介绍过re.split()函数也可以使用可选的flage参数。

在Windows计算机上可以使用tasklist命令替代who来得到类似的结果。让我们查看该命令的输出结果。

C:\WINDOWS\system32>tasklist
Image Name          PID Session Name   Session#  Mem Usage
========================= ====== ================ ======== ============
System Idle Process      0 Console         0     28 K
System             4 Console         0    240 K
smss.exe           708 Console         0    420 K
csrss.exe          764 Console         0   4,876 K
winlogon.exe         788 Console         0   3,268 K
services.exe         836 Console         0   3,932 K
. . .

可以看到,输出包含不同于who命令的输出信息,但格式是类似的,所以可以考虑之前的方案:在一个或多个空白符上执行re.split()(此处没有制表符的问题)。

问题是命令名称可能有一个空白符,而且我们(应当)更倾向于将整个命令名称连接在一起。对于内存的使用也有这个问题,我们通常得到的是“NNN K”,其中NNN是内存数量大小,K表示千字节。我们也希望将这些数据连接在一起,因此,最好分隔至少一个空白符,对吧?

不,不能这样做。注意,进程 ID(PID)和会话名称列仅仅由一个空白符分隔。这就意味着如果去掉至少一个空白符,PID和会话名称将被合并在一起作为单个结果。如果复制之前的一个脚本,重命名它为retasklist.py,然后将who命令修改为tasklist /nh(/nh选项将会去除每一列的标题),并使用一个ss+正则表达式,就将得到如下所示的输出。

Z:\corepython\ch1>python retasklist.py
['']
['System Idle Process', '0 Console', '0', '28 K']
['System', '4 Console', '0', '240 K']
['smss.exe', '708 Console', '0', '420 K']
['csrss.exe', '764 Console', '0', '5,028 K']
['winlogon.exe', '788 Console', '0', '3,284 K']
['services.exe', '836 Console', '0', '3,924 K']

. . .

已经确认,尽管我们将命令名称和内存使用字符串保存在一起,但也不经意地将PID和会话名称放在一起。因此我们不得不放弃使用split函数,而且通过正则表达式匹配实现。我们可以这样实现,然后滤除会话名称和编号,因为两者都会为输出添加数值。示例1-4显示Python 2版本下retasklist.py的最终版本。

示例1-4 处理DOS环境下tasklist命令的输出(retasklist.py)

这里的脚本使用一个正则表达式和findall()来解析DOS环境下tasklist命令的输出,但是仅仅显示感兴趣的数据。将该脚本移植到Python 3时,仅仅需要修改print()函数。

如果运行这个脚本,就能得到期望(已截断)的输出。

Z:\corepython\ch1>python retasklist.py
[]
[('System Idle Process', '0', '28 K')]
[('System', '4', '240 K')]
[('smss.exe', '708', '420 K')]
[('csrss.exe', '764', '5,016 K')]
[('winlogon.exe', '788', '3,284 K')]
[('services.exe', '836', '3,932 K')]
. . .

细致的正则表达式将会扫描全部的5列输出字符串,仅对重要的数据进行分组:命令名称、命令相应的PID,以及该命令使用的内存大小。该脚本使用已经在本章中介绍过的正则表达式的很多特性。

显然,在本小节中实现的全部脚本只向用户显示输出。实际上,我们有可能在处理数据,并将数据保存入数据库,使用得到的输出来为管理层生成报表等。

时间: 2024-11-01 20:28:54

《Python核心编程(第3版)》——1.4 一些正则表达式示例的相关文章

《Python核心编程(第二版)》——导读

前 言 欢迎走进Python核心编程 我们很高兴能帮你尽快并尽可能深入地学习Python.掌握语法是本书的一个目标,不管怎样,我们都坚信,哪怕是一个初学者,只要他能掌握Python的运作机理,他就不再仅仅是用Python"编写",而是能开发出更高效的Python应用程序.但是你知道,并不是掌握了一门语言的语法就能让你立刻登堂入室. 在本书中,你能发现许多可以立即上手的例子.为了巩固基础,你还会在每章的末尾找到有趣又富有挑战性的习题.这些初级和中级水平的习题可以检验你的学习效果,并且提升

《Python核心编程(第二版)》——1.3 特点

1.3 特点 尽管Python已经流行了超过15年,但是一些人仍旧认为相对于通用软件开发产业而言,它还是个新丁.我们应当谨慎地使用"相对"这个词,因为"网络时代"的程序开发,几年看上去就像几十年. 当人们询问:"什么是Python?"的时候,很难用任何一个具象来描述它.人们更倾向于一口气不加思索地说出他们对Python的所有感觉,Python是____(请填写),这些特点究竟又是什么呢?为了让你能知其所以然,我们下面会对这些特点进行逐一地阐释.

《Python核心编程(第二版)》——第1部分 Python核心 第1章 欢迎来到Python世界 1.1 什么是Python

第1部分 Python核心 第1章 欢迎来到Python世界 本章主题 什么是Python Python的起源 Python的特点 下载Python 安装Python 运行Python Python文档 比较Python(与其他语言的比较) 其他实现 开篇将介绍一些Python的背景知识,包括什么是Python.Python的起源和它的一些关键特性.一旦你来了兴致,我们就会向你介绍怎样获得Python,以及如何在你的系统上安装并运行它.本章最后的练习将会帮助你非常自如地使用Python,包括使用

《Python核心编程(第二版)》——1.5 运行Python

1.5 运行Python 有三种不同的办法来启动Python.最简单的方式就是交互式的启动解释器,每次输入一行Python代码来执行.另外一种启动Python的方法是运行Python脚本.这样会调用相关的脚本解释器.最后一种办法就是用集成开发环境中的图形用户界面运行Python.集成开发环境通常整合了其他的工具,例如集成的调试器.文本编辑器,而且支持各种像CVS这样的源代码版本控制工具. 1.5.1 命令行上的交互式解释器 在命令行上启动解释器,你马上就可以开始编写Python代码.在Unix,

《Python核心编程(第二版)》——1.4 下载和安装Python

1.4 下载和安装Python 得到所有Python相关软件最直接的方法就是去访问它的网站(http://python.org ).为了方便读者,你也可以访问本书的网站(http://corepython.com )并点击左侧的"Download Python"链接--我们在表格中罗列了当前针对大多数平台的Python版本,当然,这还是主要集中在"三巨头"身上:Unix,Win32和MacOS X. 正如我们在前面1.3.5小节中提到的,Python可应用的平台非常

《Python核心编程(第二版)》——1.7 比较Python(Python与其他语言的比较)

1.7 比较Python(Python与其他语言的比较) Python已经和很多语言比较过了.一个原因就是Python提供了很多其他语言拥有的特性,另外一个原因就是Python本身也是由诸多其他语言发展而来的,包括ABC.Modula-3.C.C++.Algol-68.SmallTalk.Unix shell和其他的脚本语言,等等.Python就是"浓缩的精华":Van Rossum研究过很多语言,从中吸收了许多觉得不错的特性,并将它们溶于一炉. 然而,往往因为Python是一门解释型

《Python核心编程(第二版)》——1.2 起源

1.2 起源 Guido van Rossum于1989年底始创了Python,那时,他还在荷兰的CWI(Centrum voor Wiskun- de en Informatica,国家数学和计算机科学研究院).1991年初,Python发布了第一个公开发行版.这一切究竟是如何开始的呢?像C.C++.Lisp.Java和Perl一样,Python来自于某个研究项目,项目中的那些程序员利用手边现有的工具辛苦地工作着,他们设想并开发出了更好的解决办法. 那时van Rossum是一位研究人员,对解

《Python核心编程(第二版)》——1.6 Python文档

1.6 Python文档 Python文档可以在很多地方找到,最便捷的方式就是从Python网站查看在线文档.如果你没上网,并且使用的是Win32系统,那么在C:Python2xDoc目录下会找到一个名为Python2x.chm的离线帮助文档.它使用IE接口,所以你实际上是使用网页浏览器来查看文档.其他的离线文档包括PDF和PostScript(PS)文件.最后,如果你下载了Python发行版,你会得到LaTeX格式的源文件. 在本书的网站中,我们创建了一个包括绝大多数Python版本的文档,只

《Python核心编程(第二版)》—— 1.8 其他实现

1.8 其他实现 标准版本的Python是用C来编译的,又被称为Cpython.除此之外,还有一些其他的Python实现.我们将在下面讲述些实现,除了本书中提到的这些实现以外,下面的网址还有更多的实现版本. http://python.org/dev/implementations.html Java 我们在上一节中曾经提到,还有一个可以用的 Python解释器是完全由Java写成的,名为Jython.尽管两种解释器之间存在一些细微的差别,但是它们非常接近,而且启动环境也完全相同.那Jython

《Python核心编程(第二版)》——1.9 练习

1.9 练习 1-1. 安装Python.请检查Python是否已经安装到你的系统上,如果没有,请下载并安装它. 1-2. 执行Python.有多少种运行Python的不同方法?你喜欢哪一种?为什么? 1-3. Python标准库. (a)请找到系统中Python执行程序的安装位置和标准库模块的安装位置. (b)看看标准库里的一些文件,比如string.py.这会帮助你适应阅读Python脚本. 1-4. 交互执行.启动你的Python交互解释器.你可以通过输入完整的路径名来启动它.当然,如果你