Python正则表达式findall在解析文本文件后返回空列表

问题描述

我正在尝试使用 Python 的 re 模块解析 .txt 文件中某个应用程序中的一些对话,但是尽管在用于文件样本时处理 regex101,但当我使用它时它无法正常工作打开文件并实际尝试解析它。

txt 文件的结构是 dd/mm/yyyy hh:mm - Message Author: message text\n,我试图只获取 Name: message \n 部分。我正在使用以下模式 (?<=\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}\s\-\s)(.*:.*$)。我的代码看起来或多或少如下:

buffer = open(file,'r',encoding = 'UTF-8').read()
pattern = re.compile(r'(?<=\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}\s\-\s)(.*:\s)(.*$)')
matches = re.findall(pattern,buffer)

不过,正如标题所说, findall 返回并为空列表,我不知道为什么。以下示例在 regex101 上按预期工作:

20/04/2021 09:54 - Person 1: this is an example text. Will it match?
20/04/2021 09:54 - Person 2: I think it does.

解决方法

Lookarounds 是“昂贵的”。更好地匹配您想要的内容并捕捉有趣的部分。
也就是说,您可能会使用更简单的表达方式:

int main() {
  return 123;
}

a demo on regex101.com

,

亲吻:去掉$。它匹配字符串的结尾。您需要匹配行尾,re.M 在这里可能会有所帮助。但删除 $ 更简单。

(?<=\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}\s\-\s)(.*:\s)(.*)

但即使是“亲吻”者:如果您在表达式中使用捕获组,则不需要后视或转义斜线,因为 re.findall 会返回捕获的字符串

使用

pattern = re.compile(r'\b\d{2}/\d{2}/\d{4}\s*\d{2}:\d{2}\s*-\s*(?P<name>.*):\s*(?P<message>.*)')
with open(file,'r',encoding = 'UTF-8') as buffer:
    matches = [match.groupdict() for match in pattern.finditer(test_str)]

Regex proof | Python code

说明

--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  \d{2}                    digits (0-9) (2 times)
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  \d{2}                    digits (0-9) (2 times)
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  \d{4}                    digits (0-9) (4 times)
--------------------------------------------------------------------------------
  \s*                      whitespace (\n,\r,\t,\f,and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  \d{2}                    digits (0-9) (2 times)
--------------------------------------------------------------------------------
  :                        ':'
--------------------------------------------------------------------------------
  \d{2}                    digits (0-9) (2 times)
--------------------------------------------------------------------------------
  \s*                      whitespace (\n,and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  -                        '-'
--------------------------------------------------------------------------------
  \s*                      whitespace (\n,and " ") (0 or
                           more times (matching the most amount
                           possible))