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

2024-09-27 07:35:59 发布

您现在位置:Python中文网/ 问答频道 /正文

这件事我纠结了两天,终于敢问了。你知道吗

这是我的数据(文件):

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;

我想从regex得到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”,但不是完整的块。你知道吗

需要帮助:) P.S.将在Python中使用


Tags: 文件数据tsvextregexfikwhhour
3条回答

老实说,我不会在这个工作中使用正则表达式。你知道吗

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()),)))))]

再也不敢问奋斗是否长久。我打赌你在找这个:

TSH(?:\n|.)+?(?=\nTSH|\nEXT|\nTSV;4)

Regex101上演示并在此处解释:

  • TSH很明显,符合字面意思
  • (?:\n|.)是一组非捕获字符。因为.匹配任何字符(行终止符除外),所以必须添加一个新行字符\n。你知道吗
  • (?:\n|.)+?至少匹配上述组中的一个字符
  • (?=\nTSH|\nEXT|\nTSV;4)直到达到终止条件之一。注意\n,否则,空行也将匹配。你知道吗

您可以使用以下模式:

(?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))

相关问题 更多 >

    热门问题