如何根据条件将字符串与前一个字符串组合?

How to combine string with the previous one based on condition?

我有一个消息文本文件,格式为:

with open(code_path) as f:
    contents = f.readlines()
print(contents)

['22/05/2022, 21.58 - Name: message1 \n', 
'22/05/2022, 22.07 – Name2: message2\n', 
'message2 continues\n', 
'22/05/2022, 22.09 – Name: message3\n']

目前我有字符串形式的消息。一些长消息被分成两部分。我想要一个包含所有消息的消息列表(从日期开始)。

这就是我想要的:

['22/05/2022, 21.58 - Name: message1 \n', 
'22/05/2022, 22.07 – Name2: message2 + message2 continues\n', 
'22/05/2022, 22.09 – Name: message3\n']

有办法吗?

我找到了以以下日期开头的字符串:

import re

dates = [re.findall("^[0-3][0-9]/[0-3][0-9]/20[1-2][1-9]", i) for i in contents]

但是我不知道如何继续。

一个基本的方法是使用一种缓存:通过这些行,

  • 如果该行以日期开头,则将新项目追加到缓存
  • 如果没有,请附加到最新的项目。
messages = []
for line in contents:
    if re.match(r'\d{2}/\d{2}/\d{4},\s+', line):
        messages.append([line])
    else:
        messages[-1].append(line)
 
# messages
[['22/05/2022, 21.58 - Name: message1 \n'],
 ['22/05/2022, 22.07 – Name2: message2\n', 'message2 continues\n'],
 ['22/05/2022, 22.09 – Name: message3\n']]

然后您可以 join 他们(例如 [''.join(m) for m in messages])。或者,也可以直接构建字符串,但也许您想在某些时候区分 primary/following 行,那么列表更有用。

您也可以阅读所有行,然后匹配以类似日期模式开头的行,然后匹配所有不以类似日期模式开头的行。

使用更具体的日期,例如模式:

import re

with open("file") as f:
    pattern = r"^(?:0[1-9]|[12][0-9]|3[01])/(?:0[1-9]|1[012])/\d{4},.*(?:\n(?!(?:0[1-9]|[12][0-9]|3[01])/(?:0[1-9]|1[012])/\d{4},).*)*"
    print(re.findall(pattern, f.read(), re.M))

输出

[
'22/05/2022, 21.58 - Name: message1 \n', 
'22/05/2022, 22.07 – Name2: message2\n\nmessage2 continues\n', 
'22/05/2022, 22.09 – Name: message3\n'
]

模式不太精确,但有点短:

^\d{2}/\d{2}/\d{4},.*(?:\n(?!\d{2}/\d{2}/\d{4},).*)*

说明

  • ^ 字符串锚点的开始
  • \d{2}/\d{2}/\d{4}, 匹配后跟逗号的类似日期的模式
  • .* 匹配行的其余部分
  • (?: 非捕获组作为一个整体重复
    • \n 匹配一个换行符
    • (?!\d{2}/\d{2}/\d{4},)
    • .* 匹配行的其余部分
  • )* 关闭非捕获组并可选择重复以匹配所有行

例子

import re

with open("file") as f:
    pattern = r"^\d{2}/\d{2}/\d{4},.*(?:\n(?!\d{2}/\d{2}/\d{4},).*)*"
    print(re.findall(pattern, f.read(), re.M))