Python正则表达式:如何将任何内容匹配到特定字符串,并在失败时避免回溯

Python正则表达式:如何将任何内容匹配到特定字符串,并在失败时避免回溯,python,regex,Python,Regex,我正在尝试制作一个正则表达式,它能够匹配任何特定的模式。然后,正则表达式将继续寻找其他模式,直到字符串结束,但在某些情况下,该模式将不存在,匹配将失败。现在我被困在: .*?PATTERN 问题是,在字符串不存在的情况下,由于回溯,这需要花费太多的时间。为了缩短时间,我尝试使用正向前瞻模拟原子分组,如本文所述(顺便说一句,我在python-2.7中使用re模块): 于是我写道: (?=(?P<aux1>.*?))(?P=aux1)PATTERN (?=(?P.*)(?P=aux

我正在尝试制作一个正则表达式,它能够匹配任何特定的模式。然后,正则表达式将继续寻找其他模式,直到字符串结束,但在某些情况下,该模式将不存在,匹配将失败。现在我被困在:

.*?PATTERN
问题是,在字符串不存在的情况下,由于回溯,这需要花费太多的时间。为了缩短时间,我尝试使用正向前瞻模拟原子分组,如本文所述(顺便说一句,我在python-2.7中使用re模块):

于是我写道:

(?=(?P<aux1>.*?))(?P=aux1)PATTERN
(?=(?P.*)(?P=aux1)模式
当然,当字符串不存在时,这比以前的版本快,但问题是,它不再与字符串匹配。将每一项匹配到字符串的末尾,并且在向前看之后放弃以前的状态


因此,问题是,有没有一种方法可以进行类似于
*?STRING
的匹配,并且在不存在匹配时也能够更快地失败?

Python文档简要介绍了
re.search()
re.match()函数之间的差异。具体而言,以下报价是相关的:

有时,您可能会继续使用re.match(),只需在re的前面添加。*。抵制这种诱惑,改用re.search()。正则表达式编译器对REs进行一些分析,以加快查找匹配项的过程。一个这样的分析指出了匹配的第一个字符必须是什么;例如,以Crow开头的图案必须与以“C”开头的图案匹配。该分析允许引擎快速扫描字符串以查找起始字符,只有在找到“C”时才尝试完全匹配

添加。*会导致此优化失败,需要扫描到字符串末尾,然后回溯以找到与剩余RE匹配的内容。改为使用re.search()

在您的情况下,最好将您的模式简单地定义为:

pattern = re.compile("PATTERN")

然后调用
pattern.search(…)
,当找不到模式时,它不会回溯。

您可以尝试使用
split

如果结果长度为1,则没有匹配项。如果你得到两个或更多,你知道第一个是第一场比赛。如果将拆分限制为大小为1,则会使后面的匹配短路:

"HI THERE THEO".split("TH", 1) # ['HI ', 'ERE THEO']

结果的第一个元素取决于匹配项。

一个正则表达式解决方案

^(?=(?P<aux1>(?:[^P]|P(?!ATTERN))*))(?P=aux1)PATTERN
(?P(?:[^P]| P(?!ATTERN))*)(?P=aux1)模式
解释

^(?=(?P<aux1>(?:[^P]|P(?!ATTERN))*))(?P=aux1)PATTERN
您希望像这样使用原子分组:
(?>.*)模式
,对吗?这行不通。问题是,不能在原子分组的末尾使用惰性量词:AG的定义是,一旦你在它之外,正则表达式就不会在里面回溯

因此,正则表达式引擎将匹配
*?
,由于惰性,它将跳出组以检查下一个字符是否是
p
,如果不是,它将无法在组内回溯以匹配
*
中的下一个字符

Perl中通常使用以下结构:
(?>(?:[^p]| p(?!ATTERN))*)模式
。这样,等价的
*
(此处
(?:[^P]| P(?!ATTERN))
就不会“吃掉”想要的模式

在我看来,这种模式更容易用所有格量词来理解,这些量词是专门为这些场合设计的:
(?:[^p]| p(?!ATTERN))*+模式


通过您的变通方法,这将导致上述正则表达式(添加了
^
,因为您应该将正则表达式锚定到字符串的开头或另一个正则表达式)。

正则表达式中的
字符串在哪里?我不太懂你的榜样。嗨,蒂姆。我正在寻找的模式是“src=”,我需要。*?之前可能有几个变量域,之前可能有几个变量域,我想忽略之前可能有几个变量域,之前我想忽略之前我想忽略的::::^(((?::::::(((:::::((((:::::::{{{{4}之前可能有几个变量域之前可能有几个变量域之前可能有可能有几个变量域之前之前可能有可能有几个变量,我想之前之前我想忽略之前我想忽略::::::::::::::::(((((((::::::::::::::::::::::::::::{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{3之前之前之前可能有可能有可能有可能有几个变量变量前前可能有}(?:::\s+\d{2}[^“]*)\“\s+fw=(?P\s+)\s+pri=(?P\d)\s+(?:\s+\s+)m=(?P\d+)\s+.*?src=(?P[^:\s]+)(?:(?P[^:\s]*)\S*)?\S+dst=(?P[^:\S]+)(?::(?P[^:\S]*)\S*)?\S+proto=(?P[^/]+)*?Category=\”(?P[^\“]+).$,这是我正在分析的行类型:5月18日12:47:21 id=firewall sn=XXXXXXX time=“2012-05-18 19:47:42 UTC“fw=xxx.xxx.xxx.xxx pri=6 c=1024 m=97 n=696201 src=xxx.xxx.xxx.xxx:xxxx:X0:xxxxxxxx dst=xxx.xxx.xxx.xxx:80:X2:xxxxxx.com proto=tcp/http op=GET sent=1274 rcvd=8355结果=0 dstname=www.xxxx.com arg=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX appcat=“xxxxx”appid=xxx code=31 Category=“Web Communications”你好。”。不幸的是,我无法更改代码,代码已经在使用re.search,但这是一个很好的技巧。谢谢你好,布雷特。我已经在使用re.search了,只是。*?模式是更大的regexp的一部分。我想我应该对这个问题补充一点意见来澄清这一点。谢谢谢谢!这项工作做得很好。不幸的是,PythonRe模块目前不支持AG或所有格量词,我无法将其更改为支持的正则表达式模块。不客气,很高兴我能提供帮助。别忘了将解决您问题的解决方案标记为“已接受”以结束问题,您就可以开始了!