如何在Python中查找包含两个正则表达式之间任意内容但不包含特定正则表达式的字符串?

5

我正尝试编写一个正则表达式来筛选3MB的文本并找出特定的字符串。目前它可以相对良好地工作,但存在一个问题。

我正在使用的当前表达式是

pattern = re.compile(r'[A-Z]{4} \d{3}.{4,40} \(\d\)')

这将有效地搜索整个字符串,并找到所有由4个大写字母后跟一个空格,后跟3个数字,后跟4-40个任何字符,后跟一个空格,后跟(n)其中 n 是任何数字的情况。
我要找的东西就像ACCT 220会计原理I(3)
这正是我想要的,但它有时会过早捕捉到模式。文档中有些情况下,一门课程会在模式应该开始的课程之前。例如,我最终会得到BMGT 310.ACCT 220 Principles of Accounting I (3) 我想绕过这个问题的一种方法是不允许模式在正则表达式的. {4,40} 部分包含4个大写字母。我尝试使用 ^ 来解决,但是没有效果。
例如,我尝试了类似于 [A-Z] {4} \ d {3}([^ A-Z] {4}){4,40} \(\ d \)的内容,但是结果是空列表,因为表达式没有找到任何内容。
我认为我只是还不太了解正则表达式的语法。如果有人知道如何修复我的表达式,使其可以找到所有由4个大写字母后跟一个空格,后跟3个数字,后跟4-40个任何字符(不含4个大写字母),后跟一个空格,后跟(n)其中 n 是数字的实例,那就太棒了,非常感谢。
我理解这个问题可能相当令人困惑。如果您需要更多信息,请告诉我。
1个回答

4
如果您不想匹配连续4个大写字母,可以使用负向先行断言,并使用{4,40}逐个匹配1个字符:
您当前正在使用的正则表达式片段:
.{4,40}

请翻译为:

(?:(?![A-Z]{4}).){4,40}

regex101演示

负向先行断言(?! ... )会导致在括号内的内容匹配失败。由于我们使用了(?![A-Z]{4}),如果有四个大写字母连在一起,匹配就会失败。它们是零宽度断言,因此最终的匹配不会受到影响,这也是为什么我仍然使用.进行主要匹配的原因。


一个简单的例子可能有助于解释负向先行断言如何工作以及如何理解零宽度断言:

w(?!o)

这个正则表达式将匹配w(注意没有涉及o)在waywholebelow中,但不匹配word中的w

(?![A-Z]{4}). 将匹配.,除非这个.是一个大写字母,后面跟着另外三个大写字母(即四个连续的大写字母)。

现在如果要重复这个.,不能仅使用(?![A-Z]{4}).{4,40} ,因为否定的预查只适用于第一个.而不是其他的。因此,关键是将(?![A-Z]{4}).放入一组中,然后重复:

((?![A-Z]{4}).){4,40}

最后,我更喜欢使用非捕获组(?: ... ),因为它们使正则表达式更加高效,因为它们不会存储捕获内容。
(?:(?![A-Z]{4}).){4,40}

太好了。谢谢Jerry。我之前尝试过负向先行断言,但我想我漏掉了前面的 (?:。再次感谢Jerry! - Troy Kent
@TroyKent 你好!我添加了更多关于 (?: 和负向先行断言本身的解释,以使其更清晰:) - Jerry
感谢您解释 (?: 部分 :) - Troy Kent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接