【发布时间】:2021-11-30 00:43:13
【问题描述】:
我有一个格式化的字符串,它可以有任意长度的重复部分。例如,这是我想要解析的元数据示例。
File Name: chb03_34.edf
File Start Time: 01:51:23
File End Time: 2:51:23
Number of Seizures in File: 1
Seizure Start Time: 1982 seconds
Seizure End Time: 2029 seconds
File Name: chb23_07.edf
File Start Time: 11:03:16
File End Time: 11:45:56
Number of Seizures in File: 0
File Name: chb23_08.edf
File Start Time: 11:48:05
File End Time: 14:40:27
Number of Seizures in File: 2
Seizure 1 Start Time: 325 seconds
Seizure 1 End Time: 345 seconds
Seizure 2 Start Time: 5104 seconds
Seizure 2 End Time: 5151 seconds
File Name: chb23_09.edf
File Start Time: 14:40:47
File End Time: 18:41:13
Number of Seizures in File: 4
Seizure 1 Start Time: 2589 seconds
Seizure 1 End Time: 2660 seconds
Seizure 2 Start Time: 6885 seconds
Seizure 2 End Time: 6947 seconds
Seizure 3 Start Time: 8505 seconds
Seizure 3 End Time: 8532 seconds
Seizure 4 Start Time: 9580 seconds
Seizure 4 End Time: 9664 seconds
到目前为止,我已经创建了一个正则表达式,它可以捕获第一行,但只能在一个块中捕获最后一个癫痫发作(如果存在癫痫发作)。
import re
summary = "a formatted string read"
pattern = "File Name\: (.+)\nFile Start Time\: (.+)\nFile End Time\: (.+)\nNumber of Seizures in File\: (.+)(?:\n|\r|)(?:Seizure(?: | \d )Start Time\: (\d+) seconds\nSeizure(?: | \d )End Time\: (\d+) seconds(?:\n|\r|))*"
pattern = re.compile(pattern)
for p in pattern.finditer(summary):
print(p.groups())
但是,例如最后一个块的这种模式的结果将仅捕获癫痫发作 4 的开始和结束时间。是否可以递归捕获重复的子模式?
编辑:使用regex 和模式The fourth bird 已在 cmets 中键入,我可以匹配字符串,但我在重复行中得到很多 None 值,也完全是 None 行。我怎样才能摆脱这些,或插入适当的值?
('chb23_06.edf', '08:57:57', '11:02:43', '1', '3962', '4075')
(None, None, None, None, None, None)
('chb23_07.edf', '11:03:16', '11:45:56', '0', None, None)
(None, None, None, None, None, None)
('chb23_08.edf', '11:48:05', '14:40:27', '2', '325', '345')
(None, None, None, None, '5104', '5151')
(None, None, None, None, None, None)
('chb23_09.edf', '14:40:47', '18:41:13', '4', '2589', '2660')
(None, None, None, None, '6885', '6947')
(None, None, None, None, '8505', '8532')
(None, None, None, None, '9580', '9664')
(None, None, None, None, None, None)
('chb23_10.edf', '18:41:40', '22:41:40', '0', None, None)
(None, None, None, None, None, None)
('chb23_16.edf', '13:46:32', '17:46:32', '0', None, None)
(None, None, None, None, None, None)
('chb23_17.edf', '17:46:42', '21:16:29', '0', None, None)
(None, None, None, None, None, None)
('chb23_19.edf', '02:28:28', '6:28:28', '0', None, None)
(None, None, None, None, None, None)
('chb23_20.edf', '06:28:36', '7:52:05', '0', None, None)
(None, None, None, None, None, None)
EDIT2:我完成了先前接受的答案的解决方案,但它有一些粗糙的边缘并且在某些文件中不起作用。我上传了一个有问题的文件。您可以在 here 中找到有问题的元数据示例的粘贴。
【问题讨论】:
-
由于模式中
|的交替,您会得到 None 值。您可以从结果中过滤 None 值,或者您可以使用不同的方法,通过使用初始模式,并在包含 Seizure 值的单个组中捕获最后的所有重复行,然后对该组使用 split 到获取单独的值。 -
您应该在问题中实际“运行”正则表达式的位置添加代码。
-
@FarhoodET 我认为this approach 更容易
-
您是否考虑过只逐行读取文件而不是正则表达式并以这种方式构建数据集?尽管您似乎在这两个答案之间有自己的工作答案。
-
@Jarvis 是的,但这种方式更难将每个文件的元数据实际拼凑起来。我现在接受的答案是完全可以的。