组合连续匹配并将非连续匹配与from re findall分开



我有一个字符串的格式:

my_string = 'hello|foo world|foo how|bar are|bar you|bar today|foo'

我想返回一个列表,其中后面跟着foo的所有连续单词在同一个字符串中分组在一起,但是单词之间有一个'|bar'单词在单独的字符串中。如果我尝试重复向前看:

re.findall(r'(w+(?=|foob))+',my_string)

返回
['hello', 'world', 'today']

但是我想返回的是

['hello world', 'today']

因为'hello'和'world'之间没有非foo字分隔。

在我的实际问题中,'foo'后面的单词序列在被搜索的字符串中出现的次数是未知的,'bar'可能是几种不同的模式。

我可以用几个替换来解决它,首先用split指示符替换所有非foo模式并在其上分割,然后删除foo并剥离空间:

bars_removed = re.sub('(w+|(?!foo)[a-z]+ )+','split_string',my_string)
only_foo_words = [re.sub('|foo','',x).strip() for x in bars_removed.split('split_string')]

返回所需的结果,但我觉得有一种方法可以使用findall或我遗漏的finditer来实现这一点。

你不能"排除"在同一组中捕获的其他文本之间的文本。

您需要用消费模式替换forward,提取所有连续的匹配,然后用仅仅str.replace方法删除|foo作为后处理步骤。

final_list = [x.replace('|foo','') for x in re.findall(r'w+|foo(?:s+w+|foo)*', my_string)]

参见regex演示。

细节:

  • w+-一个或多个字字符
  • |foo- a|foo字符串
  • (?:s+w+|foo)*-匹配0个或多个序列的非捕获组
    • s+-一个或多个空白
    • w+|foo-一个或多个字字符,然后是|foo字符串。

最新更新