需要REGEX帮助返回关键字之间的多行

时间:2018-08-15 10:08:21

标签: python regex string multiline

我已经挣扎了两天,终于敢问。

这是我的数据(文件):

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中使用

4 个答案:

答案 0 :(得分:1)

您可以使用以下模式:

(?s)^TSH;.*?Z01;(?=\nTSH|\nTSV;4)
  • (?s) re.DOTALL选项。
  • ^TSH;在字符串开头匹配子字符串TSH;
  • .*?懒惰地匹配任何东西。
  • Z01;匹配子字符串Z01;
  • (?=\nTSH|\nTSV;4)TSHTSV;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