正则表达式中的Python正则表达式求反

2024-04-26 11:13:16 发布

您现在位置:Python中文网/ 问答频道 /正文

给予:

ABC
content 1
123
content 2
ABC
content 3
XYZ

是否可以创建一个与“ABC[\W\W]+最短版本匹配的正则表达式?“XYZ”

本质上,我要找的是“ABC后面跟任何以XYZ结尾的字符,但是如果我在这两者之间遇到ABC,就不匹配”(但是ABC本身就是一个潜在的正则表达式,因为它并不总是一个固定的长度……所以ABC或ABcC也可以匹配)

因此,更一般地说:REGEX1后跟任何字符,以REGEX2结尾,如果REGEX1出现在中间,则不匹配。在

在这个例子中,我不想要前4行。在

(我相信这个解释可能需要…进一步的解释,哈哈)

编辑:

好吧,我知道需要进一步解释了!谢谢你到目前为止的建议。在我开始研究你们提出的每一个解决方案如何应用于我的问题时,我至少会给你们更多的思考。在

建议1:反转字符串内容和正则表达式。在

这无疑是一个非常有趣的方法,它根据我的解释解决了这个问题。在简化问题的过程中,我没有提到同样的事情可能会反过来发生,因为结束签名稍后也可能存在(并且已经证明是在我的特定情况下)。这就引出了如下所示的问题:

^{pr2}$

在本例中,我将检查“ABC through XYZ”,意思是捕获[ABC,content 1,XYZ]…但意外地捕获了[ABC,content 1,123,content 2,ABC,content 3,XYZ]。相反,这将捕获[ABC,content 3,XYZ,content 4,MNO,content 5,XYZ],而不是我们想要的[ABC,content 2,XYZ]。重点是尽量使其尽可能通用,因为我还将搜索可能具有相同起始签名(在本例中为regex“ABC”)和不同结束签名的内容。在

如果有一种方法可以构建正则表达式,使它们封装这种限制,那么只要引用一个在这种类型的字符串中搜索的正则表达式,而不是创建一个处理它的自定义搜索算法,就可以更容易地证明这一点。在

建议2:A+B+C+[^A]+[^B]+[^C]+XYZ,带有IGNORECASE标志

在ABC是有限的情况下,这似乎很好。不过,可以把它看作一个正则表达式。例如:

Hello!GoodBye!Hello.Later.

我想做的事情的简化版。我想要”你好。待会儿“给定起始正则表达式Hello[!。]以后再说!。]. 运行一些简单的像Hello[!。]待会儿[!。]会抓取整个字符串,但我想说的是如果开始正则表达式Hello[!。]存在于找到的第一个起始正则表达式实例和找到的第一个结束正则表达式实例之间,忽略它。在

这个提议下面的保护团表明,我可能会受到与括号匹配问题类似的常规语言限制的限制(Google it,考虑一下很有趣)。这篇文章的目的是想看看我是否真的不得不求助于创建一个底层算法来处理我遇到的问题。如果可能的话,我非常希望避免这种情况(在我上面给你的简单例子中,为……设计一个有限状态机是相当容易的……我希望随着它变得稍微复杂一些,它也能成立)。在

提案3:ABC(?)?:(?!ABC)。)*?带DOTALL标志的XYZ

我喜欢这个想法,如果它真的允许ABC成为regex。我明天到办公室时就得研究一下。乍一看没有什么不寻常的,但我对pythonregex是完全陌生的(对实际在代码中应用regex而不仅仅是理论上的作业)还是个新手


Tags: 方法字符串内容hello结尾情况content字符
3条回答

编辑

所以在阅读了你的进一步解释之后,我想说我之前的提议和MRAB的提议在某种程度上是相似的,在这里没有任何帮助。你的问题是实际上嵌套结构的问题。在

把你的“前缀”和“后缀”当作符号。你可以很容易地用一个左括号和一个右括号或者其他什么来代替它们,你想要的是能够只匹配最小的(然后是最深的)一对。。。在

例如,如果前缀是“ABC”,后缀是“XYZ”:

ABChello worldABCfooABCbarXYZ

您只想得到ABCbarXYZ。在

如果前缀是(,后缀是),那么字符串:

^{pr2}$

理想情况下它只能匹配(bar)。。。在

当然,您必须使用context free grammar(就像编程语言一样:C grammarPython grammar)和parser,或者使用regex以及编程语言的迭代和存储机制来创建自己的程序。在

但只有正则表达式是不可能做到的。它们可能会对你的算法有所帮助,但它们并不是为单独处理而设计的。不是那份工作的好工具。。。你不能用螺丝刀给轮胎充气。因此,您将不得不使用一些不复杂的外部机制来存储上下文,即您在嵌套堆栈中的位置。在每个上下文中使用正则表达式仍然是可能的。在

有限状态机有限的,嵌套结构有一个任意深度,需要您的自动机任意增长,因此它们不是regular languages。在

Since recursion in a grammar allows the definition of nested syntactic structures, any language (including any programming language) which allows nested structures is a context-free language, not a regular language. For example, the set of strings consisting of balanced parentheses [like a LISP program with the alphanumerics removed] is a context-free language see here

以前的提议(不再相关)

如果我这样做:

>>> s = """ABC
content 1
123
content 2
ABC
content 3
XYZ"""
>>> r = re.compile(r'A+B+C+[^A]+[^B]+[^C]+XYZ', re.I)
>>> re.findall(r,s)

我明白了

['ABC\ncontent 3\nXYZ']

这就是你想要的吗?在

regex解决方案是带有DOTALL标志的ABC(?:(?!ABC).)*?XYZ。在

还有另一种解决此问题的方法:不尝试在一个正则表达式中执行此操作。您可以用第一个正则表达式拆分字符串,然后在最后一个部分使用第二个正则表达式。在

代码是最好的解释:

s = """ABC
content 1
123
content 2
ABC
content 3
XYZ
content 4
XYZ"""

# capturing groups to preserve the matched section
prefix = re.compile('(ABC)')
suffix = re.compile('(XYZ)')

# prefix.split(s) == ['', 'ABC', [..], 'ABC', '\ncontent 3\nXYZ\ncontent 4\nXYZ']
#                          prefixmatch ^^^^^  ^^^^^^^^^^^^ rest ^^^^^^^^^^^^^^^^
prefixmatch, rest = prefix.split(s)[-2:]

# suffix.split(rest,1) == ['\ncontent 3\n', 'XYZ', '\ncontent 4\nXYZ']
#                          ^^ interior ^^   ^^^^^ suffixmatch
interior, suffixmatch = suffix.split(rest,1)[:2]

# join the parts up.
result = '%s%s%s' % (prefixmatch, interior, suffixmatch)

# result == 'ABC\ncontent 3\nXYZ'

一些要点:

  • 应该有适当的错误处理(甚至只是try: ... except ValueError: ..)来处理任何一个regex根本不匹配,从而导致列表解包失败的情况。在
  • 这假设所需的片段将在最后一次出现prefix之后立即出现,如果不是,那么您可以一次迭代prefix.split(s)两个结果(从索引1开始),并使用suffix执行相同的拆分技巧,以找到所有匹配项。在
  • 这可能相当低效,因为它创建了相当多的中间数据结构。在

相关问题 更多 >