非固定长度的正则表达式负回溯
Posted
技术标签:
【中文标题】非固定长度的正则表达式负回溯【英文标题】:Regular expression negative lookbehind of non-fixed length 【发布时间】:2014-07-28 09:52:05 【问题描述】:正如document 所说:
这称为否定后向断言。与肯定的后向断言类似,包含的模式必须只匹配一些固定长度的字符串。
所以这会起作用,目的是匹配之外的任何
,
,但不在内部:
In [188]:
re.compile("(?<!\)\,.").findall('a1,a2,a3,a4,,a6')
Out[188]:
[',a', ',a', ',a', ',']
这将适用于稍微不同的查询:
In [189]:
re.compile("(?<!\a5)\,.").findall('a1,a2,a3,a4,a5,a6')
#or this: re.compile("(?<!\..)\,.").findall('a1,a2,a3,a4,a5,a6')
Out[189]:
[',a', ',a', ',a', ',']
In [190]:
但如果查询是'a1,a2,a3,a4,_some_length_not_known_in_advance,a6'
,根据文档,以下内容将无法按预期工作:
In [190]:
re.compile("(?<![\.*])\,.").findall('a1,a2,a3,a4,a5,a6')
Out[190]:
[',a', ',a', ',a', ',', ',a']
有什么办法可以做到这一点吗?消极的回顾是错误的方法吗?
这就是lookbehind最初的设计目的(仅匹配某个固定长度的字符串)的任何原因?
【问题讨论】:
【参考方案1】:有什么办法可以做到这一点?
是的。有一个非常简单的技巧,这种情况和"regex-match a pattern unless..."很相似
这是你的简单正则表达式:
[^]*|(,)
交替的左侧|
匹配完整的 brackets
标记。我们将忽略这些匹配。右边匹配并捕获第 1 组的逗号,我们知道它们是右边的逗号,因为它们没有被左边的表达式匹配。
这是一个执行多个任务的演示,因此您可以选择(参见the demo)底部的输出:
-
计算要匹配的逗号(不是大括号之间的逗号)
显示匹配项(逗号...呵呵)
替换正确的逗号。这里我们替换为
SplitHere
,这样我们就可以执行任务 4...
用逗号分割,并显示分割后的字符串
参考
How to match (or replace) a pattern except in situations s1, s2, s3...
【讨论】:
太棒了,我觉得我走错了路。让我试试看。知道为什么负后视仅适用于固定长度的设计吗? @CTZhu 我添加了一个完整的 Python 程序,它计算正确的逗号、显示它们、替换它们并拆分字符串。 :) 这样就向您展示了如何使用这种技术完成所有主要工作。 @CTZhuAny idea why negative lookbehind only works for fixed length by design?
这实际上取决于您的正则表达式引擎。在 .NET 中,您可以拥有无限宽度的后视功能……在 Python 中也是如此!!!但前提是您使用 Matthew Barnett 的替代(而且很棒)regex
模块。至于为什么......当然,灾难性回溯的工作和机会更多,尤其是在过去的小 RAM 时代。 :) 一个老式的解决方法是反转字符串并使用前瞻。
re.compile("[^]*|(,)").findall('a1,a2,a3,a4,a5,a6')
实际上返回一个额外的''
: [',', ',', ',', ',', '']
。我有机会通过re
摆脱它吗?感谢regex
的提示,我会仔细看看。
@CTZhu 既然你喜欢这个技巧,我强烈建议你看看(或留待以后使用)linked question about exclusions in regex patterns,我写得很开心。 :)【参考方案2】:
除了使用 Negative Lookbehind,您可以使用带有平衡大括号的 Negative Lookahead。
,(?![^]*\)
例如:
>>> re.findall(r',..(?![^]*\)', 'a1,a2,a3,a4,_some_unknown_length,a5,a6,a7')
[',a2', ',a3', ',a4']
【讨论】:
谢谢!不匹配任何,
后跟[^]*\
的巧妙方法。以上是关于非固定长度的正则表达式负回溯的主要内容,如果未能解决你的问题,请参考以下文章
正则进阶之,回溯, (贪婪* 非贪婪+? 独占++)三种匹配量词