在Python中对正则表达式使用compile有什么好处吗?

h = re.compile('hello')
h.match('hello world')

vs

re.match('hello', 'hello world')

当前回答

根据Python文档:

序列

prog = re.compile(pattern)
result = prog.match(string)

等于

result = re.match(pattern, string)

但是,当表达式将在一个程序中多次使用时,使用re.compile()并保存生成的正则表达式对象以供重用会更有效。

所以我的结论是,如果你要为许多不同的文本匹配相同的模式,你最好预编译它。

其他回答

有趣的是,编译对我来说确实更有效(Win XP上的Python 2.5.2):

import re
import time

rgx = re.compile('(\w+)\s+[0-9_]?\s+\w*')
str = "average    2 never"
a = 0

t = time.time()

for i in xrange(1000000):
    if re.match('(\w+)\s+[0-9_]?\s+\w*', str):
    #~ if rgx.match(str):
        a += 1

print time.time() - t

按原样运行上述代码一次,并以相反的方式运行两个if行,编译后的正则表达式的速度将提高一倍

一般来说,我发现在编译模式时使用标志比内联使用标志更容易(至少更容易记住如何使用),比如re.I。

>>> foo_pat = re.compile('foo',re.I)
>>> foo_pat.findall('some string FoO bar')
['FoO']

vs

>>> re.findall('(?i)foo','some string FoO bar')
['FoO']

作为一个替代答案,正如我看到之前没有提到的,我将继续引用Python 3文档:

您是应该使用这些模块级函数,还是应该获取模式并自己调用它的方法?如果在循环中访问正则表达式,预编译它将节省一些函数调用。在循环之外,由于内部缓存,没有太大区别。

除了表演。

使用compile帮助我区分的概念 1. 模块(re), 2. 正则表达式对象 3.匹配对象 当我开始学习正则表达式的时候

#regex object
regex_object = re.compile(r'[a-zA-Z]+')
#match object
match_object = regex_object.search('1.Hello')
#matching content
match_object.group()
output:
Out[60]: 'Hello'
V.S.
re.search(r'[a-zA-Z]+','1.Hello').group()
Out[61]: 'Hello'

作为补充,我做了一个详尽的备忘单模块re供您参考。

regex = {
'brackets':{'single_character': ['[]', '.', {'negate':'^'}],
            'capturing_group' : ['()','(?:)', '(?!)' '|', '\\', 'backreferences and named group'],
            'repetition'      : ['{}', '*?', '+?', '??', 'greedy v.s. lazy ?']},
'lookaround' :{'lookahead'  : ['(?=...)', '(?!...)'],
            'lookbehind' : ['(?<=...)','(?<!...)'],
            'caputuring' : ['(?P<name>...)', '(?P=name)', '(?:)'],},
'escapes':{'anchor'          : ['^', '\b', '$'],
          'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
          'shorthand'       : ['\d', '\w', '\s']},
'methods': {['search', 'match', 'findall', 'finditer'],
              ['split', 'sub']},
'match_object': ['group','groups', 'groupdict','start', 'end', 'span',]
}

用下面的例子:

h = re.compile('hello')
h.match('hello world')

上面例子中的匹配方法和下面的不一样:

re.match('hello', 'hello world')

Re.compile()返回一个正则表达式对象,这意味着h是一个正则表达式对象。

regex对象有自己的匹配方法,带有可选的pos和endpos参数:

的。匹配(字符串[线程][线程]])

pos

可选的第二个参数pos给出了字符串中的一个索引 搜寻就要开始了;缺省值为0。这并不完全是 相当于对字符串进行切片;'^'模式字符匹配于 字符串的真正开始和在a之后的位置 换行符,但不一定在搜索到的索引处 开始。

尾部

可选参数endpos限制了字符串的长度 搜索;这就好像字符串有endpos个字符那么长 只搜索从pos到endpos - 1的字符 匹配。如果endpos小于pos,则找不到匹配;否则, 如果rx是编译后的正则表达式对象,则rx。搜索(字符串,0, 50)等于rx。搜索(字符串(:50),0)。

regex对象的search、findall和finditer方法也支持这些参数。

Re.match (pattern, string, flags=0)不支持,如你所见, 它的search、findall和finditer也没有。

match对象具有补充这些参数的属性:

match.pos

的search()或match()方法传递的pos的值 一个正则表达式对象。这是正则表达式所在字符串的索引 引擎开始寻找匹配。

match.endpos

传递给search()或match()方法的endpos值 正则表达式对象的。对象超出的字符串的索引 RE引擎不会去。


一个regex对象有两个唯一的,可能有用的属性:

regex.groups

模式中捕获组的数量。

regex.groupindex

将(?P)定义的任何符号组名映射到的字典 组数字。如果没有使用符号组,则字典为空 在模式中。


最后,match对象有这个属性:

match.re

其match()或search()方法的正则表达式对象 生成此匹配实例。