正则表达式结合了 2 行完整的呼叫数据

Regex combining 2 complete lines of call data

我正在准备一个 python 脚本,它只是根据用户输入的 phone 号码从 .txt 日志文件中获取通话记录。

我需要帮助编写一个捕获每个调用日志的正则表达式,以便它可以“拆分”到列表中。 每个日志都以字母开头,例如(长,北,南,东)。 在每个日志的开头是一个以“T”开头的时间戳。示例:T 02/25 00:00

以 (N,S,E) 开头的记录需要包含第二行。或者,(L) 记录没有,但它们确实有一个空的 space 下面可以包含。

本质上,我需要的是每条以 (L,N,S,E) 开头的记录及其下方的一行。

请参阅下面的通话记录示例

T                        02/25 00:00 
L 065 00 24329   12313   244.0.15.55 252.9.11.90 02/25 08:05 00:00:44 0000 0000 
                                                                
N 066 00 23442   T000185 262.1.00.09 02/25 08:05 00:00:02 A 16630
&       0000    0000                                      
S 067 00 00984   T000134             02/25 08:06 00:00:02 A 61445
&       0000    0000                                      
S 068 00 T000002 29536               02/25 08:05 00:00:36 
&       0000    0000   1234567890XXXXXX                   
E 069 00 T000002 T000185             02/25 08:06 00:00:00 
&       0000    0000   1234567890XXXXXX

例如:

L 065 00 24329   12313   244.0.15.55 252.9.11.90 02/25 08:05 00:00:44 0000 0000

将是一场比赛并且

N 066 00 23442   T000185 262.1.00.09 02/25 08:05 00:00:02 A 16630
&       0000    0000   

会是另一个,

S 068 00 T000002 29536               02/25 08:05 00:00:36 
&       0000    0000   1234567890XXXXXX   

会是另一个,依此类推...

我的正则表达式知识有限,但这是我到目前为止想出的。

N(.*)\n(.*)

这会选择以“N”开头的每条记录的第一行和第二行,但会将它们放在不同的组中。任何方向表示赞赏。

要匹配这 4 个字符中的任何一个,您可以使用字符 class [LNSE] 后跟 space 和该行的其余部分。

然后在同一捕获组中使用可选部分来匹配换行符和该行的其余部分(如果它不以任何这些字符开头)。

这也允许只匹配一行。

^[LNSE] (.*(?:\n(?![LNSE] ).*)?)
  • ^ 字符串开头
  • [LNSE] 匹配任何列出的字符和 space
  • ( 捕获 组 1
    • .* 匹配行的其余部分
    • (?:非捕获组
      • \n(?![LNSE] ).* 如果换行符不以任何列出的字符开头,则使用否定先行匹配换行符和该行的其余部分
    • )? 关闭非捕获组并使其可选
  • )关闭非捕获组

看到一个regex demo and a Python demo.

  • 如果你想匹配 0 或更多行,你 can change ?* 零次或多次重复。

  • 如果要匹配整行包括前导字符,可以省略捕获组,直接得到the match.

例如,在读取整个文件时使用re.findall获取捕获组1的值:

import re

with open('file.log', 'r') as file:
    regex = r"^[LNSE] (.*(?:\n(?![LNSE] ).*)*)"
    print(re.findall(regex, file.read(), re.MULTILINE))

这是另一种不用正则表达式的方法:

data = []
with open('file.log', 'r') as f:
    next(f)
    for line in f:
        if line[0] in ("L", "N", "S", "E"):
            data.append(line)
        else:
            data[-1] += line
print(data)
  • next(f)用于跳过第一行(T 02/25 00:00)。

假设所有日志都是两行,也可以使用列表理解:

with open('file.log', 'r') as f:
    next(f)
    lines = f.readlines()
    data = [''.join(lines[i:i+2]) for i in range(0, len(lines), 2)]
print(data)

每一行都存储在一个列表中lines(第一行除外,已被跳过)。列表理解然后将列表中的元素两个两个地连接起来。

如果日志文件存储在变量中,则相同:

lines = text.split("\n")[1:]  # [-1:] to skip the first line
data = [''.join(lines[i:i+2]) for i in range(0, len(lines), 2)]
print(data)

输出:

[
    'L 065 00 24329   12313   244.0.15.55 252.9.11.90 02/25 08:05 00:00:44 0000 0000\n                                                                \n', 
    'N 066 00 23442   T000185 262.1.00.09 02/25 08:05 00:00:02 A 16630\n&       0000    0000                                      \n', 
    'S 067 00 00984   T000134             02/25 08:06 00:00:02 A 61445\n&       0000    0000                                      \n', 
    'S 068 00 T000002 29536               02/25 08:05 00:00:36 \n&       0000    0000   1234567890XXXXXX                   \n', 
    'E 069 00 T000002 T000185             02/25 08:06 00:00:00 \n&       0000    0000   1234567890XXXXXX'
]