Python正则表达式性能:使用数千个正则表达式迭代文本的最佳方法

Python正则表达式性能:使用数千个正则表达式迭代文本的最佳方法,python,regex,python-3.x,Python,Regex,Python 3.x,我做了很多研究,但没有发现任何真正对我有帮助的东西。也许我的方法很奇怪——也许有人能把我的想法引向正确的方向 因此,情况如下: 我需要处理大量的文本(几十万)。在这些文本中,我需要查找并处理某些字符串: 我从数据库中提取的某些“静态”子字符串(如案例编号)(也有几十万个) 与正则表达式匹配的字符串,该正则表达式是动态构建的,以匹配每个可能出现的情况,其中正则表达式的最后一部分将动态设置 很明显,这会导致大量的迭代,因为每一个文本都需要输入一个函数来运行它,这个函数可以运行数十万个正则表达式,而且

我做了很多研究,但没有发现任何真正对我有帮助的东西。也许我的方法很奇怪——也许有人能把我的想法引向正确的方向

因此,情况如下:

我需要处理大量的文本(几十万)。在这些文本中,我需要查找并处理某些字符串:

  • 我从数据库中提取的某些“静态”子字符串(如案例编号)(也有几十万个)
  • 与正则表达式匹配的字符串,该正则表达式是动态构建的,以匹配每个可能出现的情况,其中正则表达式的最后一部分将动态设置
  • 很明显,这会导致大量的迭代,因为每一个文本都需要输入一个函数来运行它,这个函数可以运行数十万个正则表达式,而且最终会导致很长的运行时间

    有没有更好更快的方法来完成预期的任务?这样做的方式现在可以正常工作,但是速度非常慢,并且会在数周内给服务器带来沉重的负载

    一些示例代码可以说明我的想法:

    import re
    
    cases = []          # 100 000 case numbers from db
    suffixes = []       #  500 diffrent suffixes to try from db
    
    texts = []          # 100 000 for the beginning - will become less after initial run
    
    def process_item(text: str) -> str:
        for s in suffixes:
            pattern = '(...)(.*?)(%s|...)' % s
            x = re.findall(pattern, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which suffix matched
                pass
        for c in cases:
            escaped = re.escape(c)
            x = re.findall(escaped, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which number matched
                pass
    
        return text
    
    
    for text in texts:
        processed = process_item(text)
    

    我们高度赞赏每一个想法

    我不能发表评论,但有一些想法:

    import re
    
    cases = []          # 100 000 case numbers from db
    suffixes = []       #  500 diffrent suffixes to try from db
    
    texts = []          # 100 000 for the beginning - will become less after initial run
    
    def process_item(text: str) -> str:
        for s in suffixes:
            pattern = '(...)(.*?)(%s|...)' % s
            x = re.findall(pattern, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which suffix matched
                pass
        for c in cases:
            escaped = re.escape(c)
            x = re.findall(escaped, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which number matched
                pass
    
        return text
    
    
    for text in texts:
        processed = process_item(text)
    
    从您发布的内容来看,您想要搜索的内容似乎总是相同的,所以为什么不在运行循环之前将它们加入到大regexp中并编译大regexp呢

    通过这种方式,您不必为每次迭代编译正则表达式,只需编译一次

    e、 g

    如果您能够在
    文本中可靠地找到
    案例编号
    (例如,如果它前面有某个标识符),则最好使用
    re.search
    查找案例编号,并将案例编号设置在
    并测试该集合中的成员资格

    e、 g

    cases=[“123”,“234”]
    案例集合=集合(案例)
    文本=[“id:123”,“id:548”]
    
    sre=re.compile(r’(?我不能评论,但只是一些想法:

    import re
    
    cases = []          # 100 000 case numbers from db
    suffixes = []       #  500 diffrent suffixes to try from db
    
    texts = []          # 100 000 for the beginning - will become less after initial run
    
    def process_item(text: str) -> str:
        for s in suffixes:
            pattern = '(...)(.*?)(%s|...)' % s
            x = re.findall(pattern, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which suffix matched
                pass
        for c in cases:
            escaped = re.escape(c)
            x = re.findall(escaped, text, re.IGNORECASE)
            for match in x:
                # process the matches, where I need to know which number matched
                pass
    
        return text
    
    
    for text in texts:
        processed = process_item(text)
    
    从您发布的内容来看,您想要搜索的内容似乎总是相同的,所以为什么不在运行循环之前将它们加入到大regexp中并编译大regexp呢

    通过这种方式,您不必为每次迭代编译正则表达式,只需编译一次

    e、 g

    如果您能够在
    文本中可靠地找到
    案例编号
    (例如,如果它前面有某个标识符),则最好使用
    re.search
    查找案例编号,并将案例编号设置在
    并测试该集合中的成员资格

    e、 g

    cases=[“123”,“234”]
    案例集合=集合(案例)
    文本=[“id:123”,“id:548”]
    
    sre=re.compile(r'(?你说你是从数据库中提取的..你不能生成一个后缀字段吗?@Sayse不确定我是否正确:我从django模型中提取数据,该模型有一个带有后缀的字段。我正在对它们进行迭代,并将它们放在正则表达式模式中,使用我误解的%sAh..基本上是想,而不是想看看如何做到这一点,找出为什么有这么多的变量要开始,看看减少those@Sayse谢谢!我考虑过了。但是我想不出减少它们的方法,因为我永远不知道变量在哪里可以累积,在哪里不可以。所以每个文本都可能匹配生成的任何正则表达式--你说你从数据库中提取它们。.你不能做一个后缀字段吗?@Sayse不确定我是否正确:我从django模型中提取数据,该模型有一个带后缀的字段。我迭代它们,并将它们放在正则表达式模式中,使用我误解的%sAh。基本上,我的想法是,而不是看如何做,找出为什么有这么多变量to从开始,看看减少those@Sayse谢谢!我考虑过了。但是我想不出一个方法来减少它们,因为我永远不知道变量在哪里可以精确,在哪里不可以。所以每一个文本都可能匹配任何生成的正则表达式--谢谢你的时间和努力。今晚我将尝试你的方法。我也一样仔细考虑了如何编写正则表达式(或多个正则表达式)这可以找到文本中的每个案例编号,然后查看它是否存在于我的案例编号列表中。这应该快得多,对吧?顺便说一句,新的贡献者不能发表评论真是太遗憾了……是的,如果你可以编写regexp捕获你的
    案例编号
    ,那么它会更快。但是将
    列表
    转换为
    设置为
    set
    s对于成员资格测试来说更好。另外,如果
    案例编号
    s是“数字”,那么最好将其转换为
    int
    (节省内存)。很高兴您现在可以发表评论!:)这些是非常有用的提示,谢谢!数字是字母数字,所以我将尝试“设置”。对于我这个爱好编码的人来说,处理如此大量的数据是一件新鲜事,所以每一个优化提示都非常有用。关于:新的贡献者不能发表评论真是太遗憾了…-在这种情况下,这是一件好事-否则我们可能不会有这个完全可以接受的答案。在我看来,贡献者往往会感到遗憾无论是新的还是旧的,写下评论,这些评论都可以作为答案。谢谢你的时间和努力。今晚我将尝试你的方法。我只是想知道如何写一个正则表达式(或多个正则表达式)这可以找到文本中的每个案例编号,然后查看它是否存在于我的案例编号列表中。这应该快得多,对吧?顺便说一句,新的贡献者不能发表评论真是太遗憾了……是的,如果你可以编写regexp捕获你的
    案例编号
    ,那么它会更快。但是将
    列表
    转换为
    设置为
    set
    s对于成员资格测试来说更好。另外,如果
    案例编号
    s是“数字”,那么最好将其转换为
    int
    (节省内存)。很高兴您现在可以发表评论!:)这些是非常有用的提示,谢谢!数字是字母数字,所以我将尝试“设置”。