详解Python中的文本处理


Posted in Python onApril 11, 2015

字符串 -- 不可改变的序列

如同大多数高级编程语言一样,变长字符串是 Python 中的基本类型。Python 在“后台”分配内存以保存字符串(或其它值),程序员不必为此操心。Python 还有一些其它高级语言没有的字符串处理功能。

在 Python 中,字符串是“不可改变的序列”。尽管不能“按位置”修改字符串(如字节组),但程序可以引用字符串的元素或子序列,就象使用任何序列一样。Python 使用灵活的“分片”操作来引用子序列,字符片段的格式类似于电子表格中一定范围的行或列。以下交互式会话说明了字符串和字符片段的的用法:
字符串和分片

>>> s = 
    "mary had a little lamb"
>>> s[0] 
    # index is zero-based

    'm'
>>> s[3] = 
    'x' 
    # changing element in-place fails
Traceback (innermost last):
 File 
    "<stdin>", line 1, 
    in
     ?
TypeError: object doesn't support item assignment
>>> s[11:18] 
    # 'slice' a subsequence

    'little '
>>> s[:4] 
    # empty slice-begin assumes zero

    'mary'
>>> s[4] 
    # index 4 is not included in slice [:4]

    ' '
>>> s[5:-5] 
    # can use "from end" index with negatives

    'had a little'
>>> s[:5]+s[5:] 
    # slice-begin & slice-end are complimentary

    'mary had a little lamb'

另一个功能强大的字符串操作就是简单的 in 关键字。它提供了两个直观有效的构造:
in 关键字

>>> s = 
    "mary had a little lamb"
>>> 
    for
     c 
    in
     s[11:18]: 
    print
     c, 
    # print each char in slice
...
l i t t l e
>>> 
    if
    'x' 
    in
     s: 
    print
    'got x' 
    # test for char occurrence
...
>>> 
    if
    'y' 
    in
     s: 
    print
    'got y' 
    # test for char occurrence
...
got y

在 Python 中,有几种方法可以构成字符串文字。可以使用单引号或双引号,只要左引号和右引号匹配,常用的还有其它引号的变化形式。如果字符串包含换行符或嵌入引号,三重引号可以很方便地定义这样的字符串,如下例所示:
三重引号的使用

>>> s2 = 
    """Mary had a little lamb
... its fleece was white as snow
... and everywhere that Mary went
... the lamb was sure to go"""
>>> 
    print
     s2
Mary had a little lamb
its fleece was white as snow
    and
     everywhere that Mary went
the lamb was sure to go

使用单引号或三重引号的字符串前面可以加一个字母 "r" 以表示 Python 不应该解释规则表达式特殊字符。例如:
使用 "r-strings"

>>> s3 = 
    "this \n and \n that"
>>> 
    print
     s3
this
    and

    that
>>> s4 = r
    "this \n and \n that"
>>> 
    print
     s4
this \n 
    and
     \n that

在 "r-strings" 中,可能另外组成换码符的反斜杠被当作是常规反斜杠。在以后的规则表达式讨论中会进一步说明这个话题。

文件和字符串变量

我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。

.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:
Python .readlines() 示例

fh = open(
    'c:\\autoexec.bat')
    for
     line 
    in
     fh.readlines():
 
    print
     line

.readline() 和 .readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。另一方面,.readline() 每次只读取一行,通常比 .readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 .readline()。

如果正在使用处理文件的标准模块,可以使用 cStringIO 模块将字符串转换成“虚拟文件”(如果需要生成模块的子类,可以使用 StringIO 模块,初学者未必要这样做)。例如:
cStringIO 模块

>>> 
    import
     cStringIO
>>> fh = cStringIO.StringIO()
>>> fh.write(
    "mary had a little lamb")
>>> fh.getvalue()
    'mary had a little lamb'
>>> fh.seek(5)
>>> fh.write(
    'ATE')
>>> fh.getvalue()
    'mary ATE a little lamb'

但是,请记住,cStringIO“虚拟文件”不是永久的,这一点与真正的文件不同。如果不保存它(如将它写入一个真正的文件,或者使用 shelve 模块或数据库),则程序结束时,它将消失。

标准模块:string

string 模块也许是 Python 1.5.* 标准发行版中最常用的模块。实际上,在 Python 1.6 或更高版本中,string 模块中的功能将作为内置字符串方法(在撰写本文时,详细信息尚未发布)。当然,任何执行文本处理任务的程序也许应该用以下这行开头:
开始使用 string 的方法

      import string

一般经验法则告诉我们,如果 可以 使用 string 模块完成任务,那么那就是 正确 的方法。与 re(规则表达式)相比,string 函数通常更快速,大多数情况下他们更易于理解和维护。第三方 Python 模块,包括某些用 C 编写的快速模块,适用于专门的任务,但可移植性和熟悉性都建议只要可能就使用 string。如果您习惯于使用其它语言,也会有例外,但不如您想像的那样多。

string 模块包含了几种类型的事物,如函数、方法和类;它还包含了公共常量的字符串。例如:
string 用法例 1

>>> 
    import
     string
>>> string.whitespace
    '\011\012\013\014\015 '
>>> string.uppercase
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

虽然可以用手写出这些常量,string 版本或多或少确保了常量对于运行 Python 脚本的国家语言和平台将是正确的。

string 还包括了以常见方式(可以结合这些方式来构成几种罕见的转换)转换字符串的函数。例如:
string 用法例 2

>>> 
    import
     string
>>> s = 
    "mary had a little lamb"
>>> string.capwords(s)
    'Mary Had A Little Lamb'
>>> string.replace(s, 
    'little', 
    'ferocious')
    'mary had a ferocious lamb'

还有许多没有在这里具体说明的其它转换;可以在 Python 手册中查找详细信息。

还可以使用 string 函数来报告字符串属性,如子串的长度或位置,例如:
string 用法例 3

>>> 
    import
     string
>>> s = 
    "mary had a little lamb"
>>> string.find(s, 
    'had')5>>> string.count(s, 
    'a')4

最后,string 提供了非常 Python 化的奇特事物。.split() 和 .join() 对提供了在字符串和字节组之间转换的迅捷方法,您会发现它们非常有用。用法很简单:
string 用法例 4

>>> 
    import
     string>>> s = 
    "mary had a little lamb"
>>> L = string.split(s)
>>> L
[
    'mary', 
    'had', 
    'a', 
    'little', 
    'lamb']
>>> string.join(L, 
    "-")
    'mary-had-a-little-lamb'

当然,除了 .join() 之外,也许会利用列表来做其它事(如某些涉及我们熟悉的 for ... in ... 结构的事情)。

标准模块:re

re 模块废弃了在老的 Python 代码中使用的 regex 和 regsub 模块。虽然相对于 regex 仍然有几个有限的优点,不过这些优点微不足道,不值得在新代码中使用。过时的模块可能会从未来的 Python 发行版中删除,并且 1.6 版可能有一个改进的接口兼容的 re 模块。所以,规则表达式仍将使用 re 模块。

规则表达式很复杂。也许有人会撰写关于这个主题的书,但实际上,已经有许多人这样做了!本文尝试捕捉规则表达式的“完全形态”,让读者可以掌握它。

规则表达式是一种很简练方法,用于描述可能在文本中出现的模式。是否会出现某些字符?是否按特定顺序出现?子模式是否会重复一定次数?其它子模式是否会排除在匹配之外?从概念上说,似乎不能用自然语言了直观地描述模式。诀窍是使用规则表达式的简洁语法来编码这种描述。

当处理规则表达式时,将它作为它自己的编程问题来处理,即使只涉及一或两行代码;这些行有效地构成了一个小程序。

从最小处着手。从最基本上看,任何规则表达式都涉及匹配特定的“字符类”。最简单的字符类就是单个字符,它在模式中只是一个字。通常,您希望匹配一类字符。可以通过将类括在方括号内来表明这是一个类;在括号中,可以有一组字符或者用破折号指定的字符范围。还可以使用许多命名字符类来确定您的平台和国家语言。以下是一些示例:
字符类

>>> 
    import
     re
>>> s = 
    "mary had a little lamb"
>>> 
    if
     re.search(
    "m", s): 
    print
    "Match!" 
    # char literal
Match!
>>> 
    if
     re.search(
    "[@A-Z]", s): 
    print
    "Match!" 
    # char class
... 
    # match either at-sign or capital letter
...
>>> 
    if
     re.search(
    "\d", s): 
    print
    "Match!" 
    # digits class
...

可以将字符类看作是规则表达式的“原子”,通常会将那些原子组合成“分子”。可以结合使用 分组和 循环 来完成此操作。由括号表示分组:括号中包含的任何子表达式都被看作是用于以后分组或循环的原子。循环则由以下几个运算符中的某一个来表示:"*" 表示“零或多”;"+" 表示“一或多”;"?" 表示“零或一”。例如,请看以下示例:
样本规则表达式

ABC([d-w]*\d\d?)+XYZ

对于要匹配这个表达式的字符串,它必须以 "ABC" 开头、以 "XYZ" 结尾 -- 但它的中间必须要有什么呢?中间子表达式是 ([d-w]*\d\d?),而且后面跟了“一或多”运算符。所以,字符串的中间必须包括一个(或者两个,或者一千个)与括号中的子表达式匹配的字符或字符串。字符串 "ABCXYZ" 不匹配,因为它的中间没有必要的字符。

不过这个内部子表达式是什么呢?它以 d-w 范围内的 零或多个 字母开头。一定要注意:零字母是有效匹配,虽然使用英语单词 "some"(一些)来描述它,可能会感到很别扭。接着,字符串必须 恰好有一个数字;然后有 零或一个 附加数字。(第一个数字字符类没有循环运算符,所以它只出现一次。第二个数字字符类有 "?" 运算符。)总而言之,这将翻译成“一个或两个数字”。以下是一些与规则表达式匹配的字符串:
匹配样本表达式的字符串

ABC1234567890XYZ
ABCd12e1f37g3XYZ
ABC1XYZ

还有一些表达式与规则表达式 不匹配(想一想,它们为什么不匹配):
不匹配样本表达式的字符串

ABC123456789dXYZ
ABCdefghijklmnopqrstuvwXYZ
ABcd12e1f37g3XYZ
ABC12345%67890XYZ
ABCD12E1F37G3XYZ

需要一些练习才能习惯创建和理解规则表达式。但是,一旦掌握了规则表达式,您就具有了强大的表达能力。也就是说,转而使用规则表达式解决问题通常会很容易,而这类问题实际上可以使用更简单(而且更快速)的工具,如 string,来解决。

Python 相关文章推荐
python执行等待程序直到第二天零点的方法
Apr 23 Python
python执行子进程实现进程间通信的方法
Jun 02 Python
Python中time模块与datetime模块在使用中的不同之处
Nov 24 Python
pycharm下打开、执行并调试scrapy爬虫程序的方法
Nov 29 Python
Python编程实现使用线性回归预测数据
Dec 07 Python
使用apidocJs快速生成在线文档的实例讲解
Feb 07 Python
python主线程捕获子线程的方法
Jun 17 Python
Python3.4 tkinter,PIL图片转换
Jun 21 Python
python程序变成软件的实操方法
Jun 24 Python
python滑块验证码的破解实现
Nov 10 Python
python numpy 矩阵堆叠实例
Jan 17 Python
Python实现信息轰炸工具(再也不怕说不过别人了)
Jun 11 Python
状态机的概念和在Python下使用状态机的教程
Apr 11 #Python
在Python下使用Txt2Html实现网页过滤代理的教程
Apr 11 #Python
详解Python中DOM方法的动态性
Apr 11 #Python
将Python中的数据存储到系统本地的简单方法
Apr 11 #Python
Python中的进程分支fork和exec详解
Apr 11 #Python
Python json模块使用实例
Apr 11 #Python
Python进程通信之匿名管道实例讲解
Apr 11 #Python
You might like
PHP 柱状图实现代码
2009/12/04 PHP
php获取字段名示例分享
2014/03/03 PHP
php使用CURL不依赖COOKIEJAR获取COOKIE的方法
2015/06/17 PHP
JSON两种结构之对象和数组的理解
2016/07/19 PHP
iis6手工创建网站后无法运行php脚本的解决方法
2017/06/08 PHP
PHP获取访问设备信息的方法示例
2019/02/20 PHP
ThinkPHP5&amp;5.1实现验证码的生成、使用及点击刷新功能示例
2020/02/07 PHP
Thinkphp极验滑动验证码实现步骤解析
2020/11/24 PHP
javascript获取所有同类checkbox选项(实例代码)
2013/11/07 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
引入autocomplete组件时JS报未结束字符串常量错误
2014/03/19 Javascript
javascript实现的HashMap类代码
2014/06/27 Javascript
Nodejs极简入门教程(一):模块机制
2014/10/25 NodeJs
使用js画图之正弦曲线
2015/01/12 Javascript
JavaScript使用addEventListener添加事件监听用法实例
2015/06/01 Javascript
Immutable 在 JavaScript 中的应用
2016/05/02 Javascript
Angular2 PrimeNG分页模块学习
2017/01/14 Javascript
原生js实现验证码功能
2017/03/16 Javascript
全面解析Vue中的$nextTick
2020/12/24 Vue.js
[01:42]辉夜杯战队访谈宣传片—FANTUAN
2015/12/25 DOTA
python下如何让web元素的生成更简单的分析
2008/07/17 Python
使用Python从有道词典网页获取单词翻译
2016/07/03 Python
Python实现的递归神经网络简单示例
2017/08/11 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
在PyTorch中Tensor的查找和筛选例子
2019/08/18 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
python利用os模块编写文件复制功能——copy()函数用法
2020/07/13 Python
python获取系统内存占用信息的实例方法
2020/07/17 Python
Python3 pyecharts生成Html文件柱状图及折线图代码实例
2020/09/29 Python
Python脚本调试工具安装过程
2021/01/11 Python
美国精油公司:Plant Therapy
2019/05/17 全球购物
网络维护中文求职信
2014/01/03 职场文书
《夸父追日》教学反思
2014/02/26 职场文书
自动一体化专业求职信
2014/03/15 职场文书
社区综治工作汇报
2014/10/27 职场文书
2019大学生暑期实习心得总结
2019/08/21 职场文书