正则表达式结合文本文件中的关键字列表以解析为另一个文本文件

Regex in combination with a list of keywords from a textfile to parse into another textfile

我有一个包含很多行的模拟输出,部分内容如下所示:

    </GraphicData>
  </Connection>
  <Connection>
    <Name>ES1</Name>
    <Type>Port</Type>
    <From>Windfarm.Out</From>
    <To>BR1.In</To>
    <GraphicData>
      <Icon>
        <Points>
    </GraphicData>
  </Connection>
  <Connection>
    <Name>S2</Name>
    <Type>Port</Type>
    <From>BR1.Out</From>
    <To>C1.In</To>
    <GraphicData>
      <Icon>
        <Points>

Name 和 /Name 之间的单词因输出而异。这些名称(此处:ES1 和 S2)存储在文本文件中 (keywords.txt)。

我需要的是一个从列表 (keywords.txt) 中获取关键字的正则表达式。在 (Simulationoutput.txt) 中搜索匹配项,直到 /To> 并将这些匹配项写入另一个文本文件 (finaloutput.txt).

这是我到目前为止所做的

with open("keywords.txt", 'r') as f: 
    keywords = ast.literal_eval(f.read())

pattern = '|'.join(keywords)
results = []
with open('Simulationoutput.txt', 'r') as f:
    for line in f:
        matches = re.findall(pattern,line)
        if matches:
            results.append((line, len(matches)))

results = sorted(results, key=lambda x: x[1], reverse=True)

with open('finaloutput.txt', 'w') as f:
    for line, num_matches in results:
        f.write('{}  {}\n'.format(num_matches, line))

finaloutput.txt 现在看起来像这样:

<Name>ES1</Name>
<Name>S2</Name>

所以代码几乎可以满足我的要求,但输出应该如下所示

    <Name>ES1</Name>
    <Type>Port</Type>
    <From>Hydro.Out</From>
    <To>BR1.In</To>

    <Name>S2</Name>
    <Type>Port</Type>
    <From>BR1.Out</From>
    <To>C1.In</To>

提前致谢。

虽然我强烈建议您使用 xml.etree.ElementTree 来执行此操作,但您可以使用正则表达式来执行此操作:

import re

keywords = ["ES1", "S2"]

pattern = "|".join([re.escape(key) for key in keywords])
pattern = fr"<Name>(?:{pattern}).*?<\/To>"

with open("Simulationoutput.txt", "r") as f:
    matches = re.findall(pattern, f.read(), flags=re.DOTALL)

with open("finaloutput.txt", "w") as f:
    f.write("\n\n".join(matches).replace("\n    ", "\n"))

使用的正则表达式如下:

<Name>(?:ES1|S2).*?<\/To>
  • <Name>:匹配`.
  • (?:): Non-capturing组。
  • ES1|S2:匹配 ES1S2
  • .*?:匹配任意字符,介于零次和无限次之间,越少越好(惰性)。请注意,. 默认情况下不匹配换行符,只是因为设置了 re.DOTALL 标志。
  • <\/To>:匹配 </To>.