python2 re.sub:回溯时中止灾难模式

python2 re.sub:回溯时中止灾难模式,python,regex,Python,Regex,我正在使用re.sub() 使用一些可能导致回溯的复杂模式(由代码创建) 在Python2.6中经过一定次数的迭代后,是否有任何实用的方法中止re.sub(假设没有找到模式,或引发错误) 示例(这当然是一个哑模式,但它是由复杂的文本处理引擎动态创建的): [代码>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>再再.再.再.再.再.再.再.子(“[I1111L![I11L![[[i1l!![1245.[124>>>>>>>>>>>((((((”::

我正在使用
re.sub()
使用一些可能导致回溯的复杂模式(由代码创建)

在Python2.6中经过一定次数的迭代后,是否有任何实用的方法中止
re.sub
(假设没有找到模式,或引发错误)

示例(这当然是一个哑模式,但它是由复杂的文本处理引擎动态创建的):


[代码>>>><代码>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>再再.再.再.再.再.再.再.子(“[I1111L![I11L![[[i1l!![1245.[124>>>>>>>>>>>((((((”:::::::[[[[[[[[[[[[[[[[[[[111L111111L!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[I11L![124;(12[[[[I111L![124;(124;(12[[[[[[[[[[[[[[[[1241]Li11L![1245]除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除之外之外之外之外之外之外之外之外之外之外之外]]]]]]]]]]]]]]]]除除除除除除除除除除除除除[[[[[[[[[[[[[[[[[[l1i!|]*[i1l!|].(?:[l1i!|[[[[[^I111L![1244]鉴于鉴于[[[[[[[[[^111111L![1244]鉴于鉴于[[[[[[[[[[12]轨轨轨轨轨轨轨轨轨轨轨轨轨轨轨轨轨轨[[[[1244]除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除[L11l![1244]除除除除除124周四周四之外,还有轨轨轨轨[[[1244]上周四周四周四周四周四周四周四周四,[L1111L!除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除上述1241244之外之外以外以外以外以外以外以外以外之外,除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除上述上述上述上述上述之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外之外!!![[[[[[[[[[[[[[[[[124124[i1l!|\\w]|[i1l!|]*[l1i!|](?:[L11l![1244.[[[[[[1244]除除除上述第1 1 1 1 1月[[[[1 1 1 1 L![1244.[[1 1 1 L![[1 1 1 1 L![1244.除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除[[1 1 1 1 1 1 1 1 1 1升![1244]]除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除上述上述上述上述上述上述上述]]]]]]]]]]]]]]]除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除除:[^i1l!|\\w]|[i1l!|]*[l1i!|](?:[^l1i!|124;\\w]|[l1i!|]*'、'*'、'Ilililililili:x')
count
可以帮助您:

In [9]: re.sub ?
Type:       function
Base Class: <type 'function'>
String Form:<function sub at 0x00AC7CF0>
Namespace:  Interactive
File:       c:\python27\lib\re.py
Definition: re.sub(pattern, repl, string, count=0, flags=0)
Docstring:
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl.  repl can be either a string or a callable;
if a string, backslash escapes in it are processed.  If it is
a callable, it's passed the match object and must return
a replacement string to be used.


In [13]: a = "bbbbbbb"

In [14]: x = re.sub('b', 'a', a, count=3)

In [15]: x
Out[15]: 'aaabbbb'
[9]中的
re.sub?
类型:功能
基类:
字符串形式:
名称空间:交互式
文件:c:\python27\lib\re.py
定义:re.sub(模式、repl、字符串、计数=0、标志=0)
文档字符串:
返回通过替换最左边的字符串获得的字符串
字符串中模式的非重叠引用由
replacement repl.repl可以是字符串,也可以是可调用的;
如果是字符串,则处理其中的反斜杠转义。如果是
一个可调用函数,它传递了match对象,并且必须返回
要使用的替换字符串。
在[13]中:a=“bbb”
在[14]中:x=re.sub('b','a',a,count=3)
In[15]:x
Out[15]:“aaabbb”

除了分析正则表达式的潜在灾难性回溯(外部正则表达式的一个难题)或使用不允许回溯的不同正则表达式引擎之外,我认为唯一的方法是使用这种性质的超时:

import re
import signal

class Timeout(Exception): 
    pass 

def try_one(pat,rep,s,t=3):
    def timeout_handler(signum, frame):
        raise Timeout()

    old_handler = signal.signal(signal.SIGALRM, timeout_handler) 
    signal.alarm(t) 

    try: 
        ret=re.sub(pat, rep, s)

    except Timeout:
        print('"{}" timed out after {} seconds'.format(pat,t))
        return None

    finally:
        signal.signal(signal.SIGALRM, old_handler) 

    signal.alarm(0)
    return ret

try_one(r'^(.+?)\1+$', r'\1' ,"a" * 1000000 + "b")
尝试替换单个字符的大量重复(在本例中为一百万个“a”字符)是一种错误。完成这项任务需要花费数万年的时间(至少在Python或Perl中是这样)。Awk是不同的

尝试3秒钟后,它会优雅地超时并打印:

"^(.+?)\1+$" timed out after 3 seconds

你能发布一个示例吗?…怎么回事?你确定你的语法是格式
re.sub(substring\u to\u be\u replacement,new\u string,Orignal\u string,count)
我看不出它在这里有什么帮助;请在我的帖子中尝试带有任何count参数的正则表达式。在Python文档中:
可选参数count是要替换的模式出现的最大次数
@mercador:在你怪异的正则表达式中添加
count
关键字不会让我的粉丝们慢下来。@mercador:count将在固定的迭代次数后停止re.sub..这是您的问题…警告,
signal.sigallarm
依赖于平台,在线程中无法正常运行environments@thewolf:这适用于Python2.5+,但不适用于Python2.4。在2.4上,当
re.sub(r'^(.+?)\1+$,r'\1',“a”*1000000+“b”)时
正在执行,
signal.SIGALARM
似乎被进程忽略了。有什么方法可以让它在2.4上工作吗?@mercador:你在问题中提到了Python 2.6……Python 2.4已经快9年了。也许可以安全地假设一个更新的版本?@wolf:是的,我提到了Python 2.6。结果是,我们的两台机器仍然有Python 2.4,升级它们现在将是一个巨大的考验。它们将在某个时候与Python 2.4一起退役。我不明白的是Python 2.4有signal.alarm(),它可以工作,只是当您计划一个警报,然后运行一个CPU密集型操作时(如
re.sub
),信号处理程序不会被调用。如果改为运行
while
循环,它会被调用。为什么?这种行为不同于2.5和2.6,但似乎没有记录在案?@mercador:我不知道。我没有Python 2.4,所以无法检查它。