Python中使用正则表达式(六)

6、常见的问题


对于一些应用正则表达式是一个强有力的工具,但是在某些方面它们的行为不直观,并且有时它们不按照你期望的方法去做。本节将指出一些最常见的易犯的错误。

6.1、使用字符串方法

某些时候使用re模块是个错误。如果你正在匹配一个固定的字符串或一个单一的字符类别,并且你没有使用任何的re特性如IGNORECASE标志,那么就没有必要使用正则表达式。字符串有几个方法来执行对固定字符串的操作,并用通常更快。

举 一个使用一字符串代替另一固定字符串的例子,例如,你要用"deed"代替"word"。re.sub()好像适合用来处理这个,但是考虑replace ()方法。注意,replace()也将替换单词中的"word",转换"swordfish"为"sdeedfish",不过正则表达式也是可以做到 的。(要避免替换单词的一部分,模式不得不写成 /bword/b,这是为了要求 "word" 两边有一个单词边界。这个工作超过了replace的能 力。)

另一个常见的任务是删除一个字符串中的一个字符或用另一个字符替换它。你也许使用如re.sub('/n', ' ', S)来做这种事,但 translate() 能够实现这两个任务,而且比任何正则表达式操作起来更快。 

总之,在使用re模块之前,请先考虑你的问题能否使用一个更快更简单的字符串方法来解决。

6.2、match()与search()

match() 函数只检查 RE 是否在字符串开始处匹配,而search()则为了匹配而向前扫描整个字符串。记住这一区别是重要的。记住,match()仅在开始于0处匹配时才报告匹配成功,如果匹配不是从 0 开始的,match() 将不会报告它。
>>> print re.match('super', 'superstition').span()  
(0, 5)
>>> print re.match('super', 'insuperable')    
None

另一方面,search()将向前扫描整个字符串,并报告它找到的第一个匹配。
>>> print re.search('super', 'superstition').span()
(0, 5)
>>> print re.search('super', 'insuperable').span()
(2, 7)


有 时你可能倾向于使用 re.match(),只在正则表达式的前面部分添加 .* 。抵止住这个倾向,并使用re.search来代替。 正则表达式编译 器对正则表达式做一些分析以便加速寻找匹配的处理工作。如分析指出匹配的第一个字符必须是什么;例如,一个以Crow开始的模式必须匹配以一个"C"开始 的。分析机可以让引擎快速扫描字符串以找到开始字符,并只在 "C" 被发现后才试着全部匹配。

添加 .* 会使这个优化失败,这就要扫描到字符串尾部,然后回溯以找到 RE 剩余部分的匹配。请使用 re.search() 代替。

6.3、贪婪的与不贪婪的

当重复一个正则表达式时,如用 a*,操作结果是尽可能多地匹配模式。当你试着匹配一对对称的定界符,如 HTML 标志中的尖括号时这个结果经常会困扰你。匹配单个HTML标记的无知的模式不工作,因为 .* 的本质是“贪婪”的。
>>> s = 'Title'
>>> len(s)
32
>>> print re.match('<.*>', s).span()
(0, 32)
>>> print re.match('<.*>', s).group()
Title

匹配从 "" 中的 ">",这并不是你所想要的结果。

在 这种情况下,解决的方案是使用不贪婪的限定符 *?、+?、?? 或 {m,n}?,这将尽可能匹配小的文本。在上面的例子里, ">" 在第一个  "<" 匹配之后被立即尝试,当它失败时,引擎一次增加一个字符,并在每步重试 ">"。这个处理将得到正确的结果: 
>>> print re.match('<.*?>', s).group()


注意用正则表达式分析 HTML 或 XML 是痛苦的。象这样的任务用 HTML 或 XML 解析器。

6.4、不使用re.VERBOSE

现在你大概注意到正则表达式是非常简洁的符号,但它们不是易读的。中度复杂的正则表达式可以变成反斜杠、圆括号和元字符的长长集合,使它们难以被读懂。

对于这样的正则表达式,当编译正则表达式时指定 re.VERBOSE 标志是有帮助的,因为它允许你编辑正则表达式的格式使之更清楚。

re.VERBOSE  标志有点作用。正则表达式中不在字符类中的空白符被忽略。这就意味着象 dog | cat 这样的表达式和可读性差的 dog|cat等同,但  [a b] 将仍就匹配字符 "a"、"b" 或 空格。另外,你也可以把注释放到正则表达式中;注释是从 "#" 一直到换行。当使用三引号字符串时, 可以使正则表达式更优美:
pat = re.compile(r"""
 /s*                 # Skip leading whitespace
 (?P
[^:]+)   # Header name
 /s* :               # Whitespace, and a colon
 (?P.*?)      # The header's value -- *? used to
                     # lose the following trailing whitespace
 /s*$                # Trailing whitespace to end-of-line
""", re.VERBOSE)

这比下面的更易读:
pat = re.compile(r"/s*(?P
[^:]+)/s*:(?P.*?)/s*$")  

你可能感兴趣的:(正则表达式,python,html,search,任务,工作)