我使用以下正则表达式:
((FFD8FF).+?((FFD9)(?:(?!FFD8).)*))
我需要使用正则表达式执行以下操作:
FFD8FF
FFD9
FFD8FF
FFD9
,不包括之后的任何内容
我所需要的是除了它找到并保留最后一个FFD9之后的任何垃圾。如何让它跳回上一个FFD9
?
这是我用这个表达式搜索的字符串:
asdfasdfasasdaFFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9asdflasdflasdfFFD9asdfasdfFFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9
非常感谢你的帮助。
更多信息:
我有一个需要搜索的起始值和结束值列表(FFD8FF和FFD9只是一对)。他们在列表中。因此,我使用r.compile在for循环中动态创建表达式,该循环遍历不同的值。我有以下代码,但它返回0匹配:
regExp = re.compile("FD8FF(?:[^F]|F(?!FD8FF))*FFD9")
matchObj = re.findall(regExp, contents)
在上面的代码中,我只是尝试使用普通的正则表达式,甚至没有从列表中获取值(看起来像这样):
regExp = re.compile(typeItem[0] + "(?:[^" + typeItem[0][0] + "]|" + typeItem[0][0] + "(?!" + typeItem[0] + "))*" + typeItem[1])
为什么没有任何匹配的任何其他想法?
编辑:
我发现我忘了包含旗帜。现在包含标志以忽略大小写和多行。我现在有
regExp = re.compile(typeItem[0] + "(?:[^" + typeItem[0][0] + "]|" + typeItem[0][0] + "(?!" + typeItem[0] + "))*" + typeItem[1],re.M|re.I)
虽然现在我收到了内存错误。有没有办法让这个更有效率?我使用表达式搜索成千上万行(使用上面的findall
表达式)
答案 0 :(得分:3)
一种简单的方法是使用它:
FFD8FF(?:[^F]|F(?!FD8FF))*FFD9
说明:
FFD8FF
(?: # this group describe the allowed content between the "anchors"
[^F] # all that is not a "F"
| # OR
F(?!FD8FF) # a "F" not followed by "FD8FF"
)* # repeat (greedy)
FFD9 # until the last FFD9 before FFD8FF
即使贪婪量词用于该组,正则表达式引擎也会回溯以找到最后一个“FFD9”子字符串。
如果要确保存在FFD8FF,可以在模式的末尾添加前瞻:
FFD8FF(?:[^F]|F(?!FD8FF))*FFD9(?=.*?FFD8FF)
您可以通过模拟一个限制回溯的原子组来优化此模式,并允许在组内使用量词:
FFD8FF(?:(?=([^F]+|F(?!FD8FF)))\1)*FFD9
这个技巧使用了这样一个事实:一旦前括号到达,前瞻的内容自然是原子的。因此,如果将一个组封装在一个内部具有捕获组的前瞻中,则只需要在后面放置后向引用以获得“原子”(不可分割的子串)。 当正则表达式引擎需要回溯时,它将逐个原子地回溯,而不是逐字符地逐字回溯。
如果在此技巧之前需要捕获组,请不要忘记更新反向引用的数量,例如:
(FFD8FF(?:(?=([^F]+|F(?!FD8FF)))\2)*FFD9)
(FFD8FF((?:(?=([^F]+|F(?!FD8FF)))\3)*)FFD9)
工作示例:
>>> import re
>>> yourstr = 'asdfasdfasasdaFFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9asdflasdflasdfFFD9asdfasdfFFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9'
>>> p = re.compile(r'(FFD8FF((?:(?=([^F]+|F(?!FD8FF)))\3)*)FFD9)(?=.*?FFD8FF)')
>>> re.findall(p, yourstr)
[('FFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9asdflasdflasdfFFD9', 'asdfalsjdflajsdfljasdfasdfasdfasdfFFD9asdflasdflasdf', 'D9asdflasdflasdf')]
变体:
(FFD8FF((?:(?=(F(?!FD8FF)[^F]*|[^F]+))\3)*)FFD9)(?=.*?FFD8FF)
答案 1 :(得分:1)
由于您的应用程序架构不限于一个正则表达式,因此将其分解为几个步骤:
您希望以每个FFD8FF
开头的单位分解文本。只需使用在下一个FFD8FF
:re.findall(r"FFD8FF.*?(?=FFD8FF)", contents)
之前结束的非贪婪搜索。 (这使用了预测,在我看来过度使用;但它可以让你为下一个字符串保存最终的FFD8FF。)
然后,您需要修剪每个此类字符串,使其在 last FFD9
处结束。最简单的方法是使用贪婪的搜索:re.search(r"^.*FFD9", part)
。像这样:
for part in re.findall(r"FFD8FF.*?(?=FFD8FF)", contents):
print(re.search(r"^.*FFD9", part).group(0))
简单,可维护和高效。
答案 2 :(得分:0)
我就是这样做的:
>>> re.search(r'((FFD8FF).+?(FFD9))(?:((?!FFD9).)+FFD8FF)', s).groups()
('FFD8FFasdfalsjdflajsdfljasdfasdfasdfasdfFFD9asdflasdflasdfFFD9',
'FFD8FF',
'FFD9',
'f')
第二部分只搜索不包含以FFD9
结尾的FFD8FF
的字符串。
它包含您的搜索组件,因此您仍然可以在正则表达式中替换它们。但是对于像这样复杂的东西,我会避免使用正则表达式。
不过,感谢您发布高质量的正则表达式问题,而不是通常的垃圾邮件。