我已经挣扎了两天,终于敢问。
这是我的数据(文件):
EXH;2;20180514103023+00;
TSH;FI__REPLACEMGA_LOS_92_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_92_12345;;;;;;LOS_92_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_93_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_93_12345;;;;;;LOS_93_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_96_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_96_12345;;;;;;LOS_96_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_97_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_97_12345;;;;;;LOS_97_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
EXT;
我想从正则表达式中获取4个块(4个匹配项),例如:
TSH;FI__REPLACEMGA_LOS_92_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_92_12345;;;;;;LOS_92_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
在每次比赛中,我都会应用一些正则表达式。但是现在,我无法进行正则表达式来返回这些匹配项。
这是我尝试过的:
(TSH;FI(?:.*?\r?\n?)*(?<=TSH;))+
但是这一次仅返回2个匹配项(每秒),可能是因为它消耗了每个“ TSH”;比赛结束后的那个方块。
(TSH;(?:.*?\r?\n?)*)+(?<=\nTSH;)
此人找到4个“ TSH”;但不是完整的区块。
需要帮助:) 附言将在Python中使用
答案 0 :(得分:1)
您可以使用以下模式:
(?s)^TSH;.*?Z01;(?=\nTSH|\nTSV;4)
(?s)
re.DOTALL
选项。^TSH;
在字符串开头匹配子字符串TSH;
。.*?
懒惰地匹配任何东西。Z01;
匹配子字符串Z01;
。(?=\nTSH|\nTSV;4)
。 TSH
或TSV;4
的正面预测。您可以在线体验here。
在Python中,您可以使用:
print(re.findall(r'^TSH;.*?Z01;(?=\nTSH|\nTSV;4)',mystr,re.DOTALL|re.MULTILINE))
答案 1 :(得分:1)
再也不敢问斗争时间是否更长。我敢打赌,您正在寻找这个:
TSH(?:\n|.)+?(?=\nTSH|\nEXT|\nTSV;4)
Regex101上的演示和此处的说明:
TSH
很明显,字面上匹配(?:\n|.)
是一个非捕获字符组。因为.
匹配任何字符(行终止符除外),所以您必须添加新的行字符\n
。(?:\n|.)+?
匹配上述组中的至少一个字符(?=\nTSH|\nEXT|\nTSV;4)
,直到达到终止条件之一为止。请注意\n
,否则,也将匹配一个空行。答案 2 :(得分:0)
老实说,我完全不会使用正则表达式来完成这项工作。
只用TSH
分割,然后稍后进行清理似乎要容易得多。
因此,如果数据位于data
中,我们可以执行以下操作:
blocks = [ "TSH" + block for block in data.split("TSH") ]
第一个块是虚假的,所以要摆脱它:
blocks = blocks[1:]
最后一块包含额外的"EXT;\n"
,所以也要清理它:
blocks = blocks[-1] = blocks[-1][:-len("EXT;\n")]
就这样,您就完成了。
当然,这是假设TSH
不会出现在数据中间。如果是这样,您可以按换行符拆分数据,查看哪些行以TSH
开头,然后使用这些索引来精简数据。
这是一个令人讨厌的单行代码:
["\n".join(data.split()[i:j]) for i, j in zip(*(lambda a, b: (a, next(b) and b))(*itertools.tee(itertools.chain(( i for i, line in enumerate(data.split()) if line.startswith("TSH")), (len(data.split()),)))))]
答案 3 :(得分:0)
已更正测试数据:
EXH;2;20180514103023+00;
TSH;FI__REPLACEMGA_LOS_92_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_92_12345;;;;;;LOS_92_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_93_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_93_12345;;;;;;LOS_93_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_96_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_96_12345;;;;;;LOS_96_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
TSH;FI__REPLACEMGA_LOS_97_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_97_12345;;;;;;LOS_97_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
EXT;
带有
这样的表达式(?s)^TSH;.*?Z01;(?=\nTSH|\nEXT)
我确实得到了匹配,就像我想要的TSH块...。记录如下:
TSH;FI__REPLACEMGA_LOS_92_12345;1;1;HOUR;kWh;24;201805120000+00;201805130000+00;LOS_92_12345;;;;;;LOS_92_12345;;;
TSV;1;201805120000+00;0.000000;Z01;
TSV;2;201805120100+00;0.000000;Z01;
TSV;3;201805120200+00;0.000000;Z01;
TSV;4;201805120300+00;0.000000;Z01;
非常感谢UnbearableLightness