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 步)是去除尾随空格。
此问题的关键是确保使用 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 步)是去除尾随空格。