Python re.findall 没有环顾四周,也没有多行模式(AND NOT SPLIT())来捕获除指定字符串之外的所有内容

Python re.findall without lookarounds and not multiline mode (AND NOT SPLIT()) to capture everything besides specified string

此问题的关键是确保使用 re.findall 不使用环顾四周并且不在多行模式下。这部分是因为我还想将它移植到不支持环视的正则表达式库中。

假设我有以下字符串:

>>> a = '''bleh blee BLOO
GOO ruu bum LUM Tum
sss ddf GHH rty

[[[BREAK]]]

gumpty RUMPTY BOBBY 
JOE low blow

[[[BREAK]]]

BEEP boop bob
yellow green tam nim
reese yob

[[[BREAK]]]

'''

我想做的是使用 re.findall 捕获所有不是 "\n\n\[\[\[BREAK\]\]\]\n\n" 而不使用lookarounds 也不在多行模式下,是的,我希望双 \n 成为排除字符串的一部分。

想要的OUTPUT如下:

>>> b[0]
'bleh blee BLOO\nGOO ruu bum LUM Tum\nsss ddf GHH rty'
>>> b[1]
'gumpty RUMPTY BOBBY\nJOE low blow'
>>> b[2]
'BEEP boop bob\nyellow green tam nim\nreese yob'

我很清楚我可以使用 split() 和 re.split(),但我想更纯粹地了解如何为此正确编写正则表达式,因为我确信它将来会出现。

.

让我烦恼的是,即使在环视方面,如果没有作弊,我在做这件事时也会遇到问题——下面我告诉它捕获在我忽略的字符串之前不包含“\[”的每个字符串,但这并不能说明“\[”可能存在的可能性:

>>> b = re.findall('[^\[]+(?=\n\n\[\[\[BREAK\]\]\]\n\n)', a)

输出

>>> b[0]
'bleh blee BLOO\nGOO ruu bum LUM Tum\nsss ddf GHH rty'
>>> b[1]
'gumpty RUMPTY BOBBY\nJOE low blow'
>>> b[2]
'BEEP boop bob\nyellow green tam nim\nreese yob'

任何人都可以提供见解吗?实际上,为了让我更好地理解它,甚至可能会邀请改进我的环视部分。

其实很简单:

(.+?)
\[{3}BREAK\]{3}

... 使用 DOTALL 模式,请参阅 a demo on regex101.com。如果不支持 DOTALL,您可以将其更改为 [\s\S]\s 表示所有空格,而 \S 表示所有非空格字符。 [..] 是一个字符 class,所以如果你把 \s\S 放在里面,你最终会得到 所有字符 .在每个表达式之后都有一个量词,在本例中是所谓的 惰性量词 :它会尝试在任何情况下停止,除非由于后面的表达式而感到被迫进一步扩展。在这种情况下,它只会在随后立即找到 [[[BREAK]]] 时停止(因此它与先行比较但 消耗 个字符而不是仅仅断言特定位置)。


Python 中,这将是:

import re
rx = re.compile(r'(.+?)\[{3}BREAK\]{3}', re.DOTALL)
matches = [match.group(1).strip() for match in rx.finditer(a)]
print(matches)
# ['bleh blee BLOO\nGOO ruu bum LUM Tum\nsss ddf GHH rty', 'gumpty RUMPTY BOBBY \nJOE low blow', 'BEEP boop bob\nyellow green tam nim\nreese yob']

好的,我想你可以这样做。
(?:^(?:\n\n\[\[\[BREAK\]\]\]\n\n)+)?([\S\s]*?)(?:(?:\n\n\[\[\[BREAK\]\]\]\n\n)+|$)

你必须匹配你不想要的东西才能移动当前位置
过去它。就是那样子。

展开

 (?:
      ^
      (?: \n\n \[\[\[BREAK\]\]\] \n\n )+
 )?
 ( [\S\s]*? )                  # (1)
 (?:
      (?: \n\n \[\[\[BREAK\]\]\] \n\n )+
   |  $ 
 )

如果你想学习正则表达式,那么请看看别人的帖子。如果您想完成工作,str.split() 更简单:

In [1]: a = '''bleh blee BLOO
   ...: GOO ruu bum LUM Tum
   ...: sss ddf GHH rty
   ...: 
   ...: [[[BREAK]]]
   ...: 
   ...: gumpty RUMPTY BOBBY 
   ...: JOE low blow
   ...: 
   ...: [[[BREAK]]]
   ...: 
   ...: BEEP boop bob
   ...: yellow green tam nim
   ...: reese yob
   ...: 
   ...: [[[BREAK]]]
   ...: 
   ...: '''

In [2]: a.split('[[[BREAK]]]')
Out[2]: 
['bleh blee BLOO\nGOO ruu bum LUM Tum\nsss ddf GHH rty\n\n',
 '\n\ngumpty RUMPTY BOBBY \nJOE low blow\n\n',
 '\n\nBEEP boop bob\nyellow green tam nim\nreese yob\n\n',
 '\n\n']

In [3]: [block.strip() for block in a.split('[[[BREAK]]]')]
Out[3]: 
['bleh blee BLOO\nGOO ruu bum LUM Tum\nsss ddf GHH rty',
 'gumpty RUMPTY BOBBY \nJOE low blow',
 'BEEP boop bob\nyellow green tam nim\nreese yob',
 '']

在第 2 行中,我们几乎得到了我们想要的,接下来的步骤(第 3 步)是去除尾随空格。