regex 改进python正则表达式性能

hrysbysz  于 2023-01-27  发布在  Python
关注(0)|答案(6)|浏览(124)

尝试改进下面的正则表达式:

urlpath=columns[4].strip()
                                urlpath=re.sub("(\?.*|\/[0-9a-f]{24})","",urlpath)
                                urlpath=re.sub("\/[0-9\/]*","/",urlpath)
                                urlpath=re.sub("\;.*","",urlpath)
                                urlpath=re.sub("\/",".",urlpath)
                                urlpath=re.sub("\.api","api",urlpath)
                                if urlpath in dlatency:

这将转换一个URL,如下所示:

/api/v4/path/apiCallTwo?host=wApp&trackId=1347158

api.v4.path.apiCallTwo

想尝试和提高regex尽可能的性能,因为每5分钟这个脚本运行约50,000个文件,需要约40秒的整体运行。
谢谢

bgibtngc

bgibtngc1#

试试这个:

s = '/api/v4/path/apiCallTwo?host=wApp&trackId=1347158'
re.sub(r'\?.+', '', s).replace('/', '.')[1:]
> 'api.v4.path.apiCallTwo'

要获得更好的性能,请编译一次正则表达式,然后重用它,如下所示:

regexp = re.compile(r'\?.+')
s = '/api/v4/path/apiCallTwo?host=wApp&trackId=1347158'

# `s` changes, but you can reuse `regexp` as many times as needed
regexp.sub('', s).replace('/', '.')[1:]

更简单的方法,不使用正则表达式:

s[1:s.index('?')].replace('/', '.')
> 'api.v4.path.apiCallTwo'
c9qzyr3d

c9qzyr3d2#

包含urlparse的单行程序:

urlpath = urlparse.urlsplit(url).path.strip('/').replace('/', '.')
txu3uszq

txu3uszq3#

这是我的一行解决方案(编辑)。

urlpath.partition("?")[0].strip("/").replace("/", ".")

正如其他一些人所提到的,速度的提高在这里可以忽略不计。除了使用re.compile()预编译表达式外,我会从其他地方开始寻找。

import re

re1 = re.compile("(\?.*|\/[0-9a-f]{24})")
re2 = re.compile("\/[0-9\/]*")
re3 = re.compile("\;.*")
re4 = re.compile("\/")
re5 = re.compile("\.api")
def orig_regex(urlpath):
    urlpath=re1.sub("",urlpath)
    urlpath=re2.sub("/",urlpath)
    urlpath=re3.sub("",urlpath)
    urlpath=re4.sub(".",urlpath)
    urlpath=re5.sub("api",urlpath)
    return urlpath

myregex = re.compile(r"([^/]+)")
def my_regex(urlpath):
    return ".".join( x.group() for x in myregex.finditer(urlpath.partition('?')[0]))

def test_nonregex(urlpath)
    return urlpath.partition("?")[0].strip("/").replace("/", ".")

def test_func(func, iterations, *args, **kwargs):
    for i in xrange(iterations):
        func(*args, **kwargs)

if __name__ == "__main__":
    import cProfile as profile

    urlpath = u'/api/v4/path/apiCallTwo?host=wApp&trackId=1347158'
    profile.run("test_func(orig_regex, 10000, urlpath)")
    profile.run("test_func(my_regex, 10000, urlpath)")
    profile.run("test_func(non_regex, 10000, urlpath)")

结果

Iterating orig_regex 10000 times
     60003 function calls in 0.108 CPU seconds

....

Iterating my_regex 10000 times
     130003 function calls in 0.087 CPU seconds

....

Iterating non_regex 10000 times
     40003 function calls in 0.019 CPU seconds

如果不对5个正则表达式进行重新编译,将导致

running <function orig_regex at 0x100532050> 10000 times
     210817 function calls (210794 primitive calls) in 0.208 CPU seconds
koaltpgm

koaltpgm4#

一行一行地检查:
我们没有捕获或分组,所以不需要(),并且/在Python的正则表达式中不是特殊字符,所以不需要转义:
urlpath = re.sub("\?.*|/[0-9a-f]{24}", "", urlpath)
/替换/后面的零重复内容是没有意义的:
urlpath = re.sub("/[0-9/]+", "/", urlpath)
使用字符串方法删除固定字符及其后面的所有内容的速度更快:
urlpath = urlpath.partition(";")[0]
使用字符串方法将一个固定字符串替换为另一个固定字符串的速度也更快:
urlpath = urlpath.replace("/", ".")
urlpath = urlpath.replace(".api", "api")

tyky79it

tyky79it5#

您还可以编译re语句来提高性能,
例如:

compiled_re_for_words = re.compile("\w+")
compiled_re_for_words.match("test")
xzv2uavs

xzv2uavs6#

你确定你需要正则表达式吗?
即:

urlpath = columns[4].strip()
urlpath = urlpath.split("?")[0]
urlpath = urlpath.replace("/", ".")

相关问题