【问题标题】:How to split this YAML file into two new yml files?如何将此 YAML 文件拆分为两个新的 yml 文件?
【发布时间】:2022-01-11 15:48:46
【问题描述】:

我正在尝试将一个 yml 文件拆分为两个新的 yml 文件。第一个文件只包含键,第二个文件只包含值。

这是我的代码:

# Import
from itertools import zip_longest
import yaml
import re

# Saves values to another yml file
with open("testFile.yml") as a_file:
  for object in a_file:
    stripped_object = object.rstrip()
    found = False
    file = open("ValuesfileNotTranslated.yml", "a")
    if re.split(':|=', stripped_object, maxsplit=1)[-1].strip():
      file.writelines(re.split(':|=', stripped_object, maxsplit=1)[-1].strip() + "\n" )

# Saves keys to another yml file
with open("testFile.yml") as a_file:
  for object in a_file:
    if object[:object.find(":")]:
      file = open("Keysfile.yml", "a")
      file.writelines(object[:object.find(":")] + ":" + "\n")
    else:
      file.writelines(object)
    

这是我要拆分的 yml 文件:

 channels:
      channel: Channel
      headline: Channels
      empty_msg: There are currently no channels.
      add: Add new channel
      reorder: Change channel order
      actions:
        show: View
        edit: Edit
        remove: Remove

当我尝试运行代码时,我得到了 2 个输出:

  • 文件 1:仅包含密钥(此文件正确)
channels:
      channel:
      headline:
      empty_msg:
      add:
      reorder:
      actions:
        show:
        edit:
        remove:

注意:共有 10 行。

  • 文件 2:仅包含值(此文件不正确)
Channel
Channels
There are currently no channels.
Add new channel
Change channel order
View
Edit
Remove

注意:只有 8 行。 第二个文件也应该是 10 行。例如 file 1 中的 line 3 必须与 file 2 中的 line 3 匹配(例如 "headline" = "频道”)

当我们查看输入的 yml 文件时:

channels:
      channel: Channel

例如,我们看到这 2 行。 “频道:”和“频道”被保存到密钥文件中,但唯一保存到值文件中的是“频道”。因此“通道:”之后的空格不会保存到值文件中。我认为存在问题,但我无法弄清楚我必须在代码中进行哪些更改才能获得正确的输出。

有人可以帮忙吗?

谢谢!

【问题讨论】:

  • 当你使用 rstrip() 时,你会删除行中最后一个非空白字符之后的所有空白,所以当你尝试在其上运行 re.split() 时,它只返回 1结果而不是两个。
  • @MattDMo 但是当我删除rstrip() 时,什么也没有发生。当我删除 rstrip()strip() 时,会创建一个额外的空格。

标签: python split yaml


【解决方案1】:

正则表达式应该可以完成这项工作:

import re

regex_first_part  = r"(.*)(?=:)"
regex_second_part = r":.*$"

test_str = (" channels:\n"
    "      channel: Channel\n"
    "      headline: Channels\n"
    "      empty_msg: There are currently no channels.\n"
    "      add: Add new channel\n"
    "      reorder: Change channel order\n"
    "      actions:\n"
    "        show: View\n"
    "        edit: Edit\n"
    "        remove: Remove")

matches = re.findall(regex_first_part, test_str, re.MULTILINE)
# Lets remove the empty lines and make a string with the output
first_part = "\n".join(list(filter(None, matches)))

print(first_part)

matches = re.findall(regex_second_part, test_str, re.MULTILINE)
second_part = [m.replace(':', '').strip() for m in matches]
second_part = "\n".join(second_part)

print(second_part)

输出:

 channels
      channel
      headline
      empty_msg
      add
      reorder
      actions
        show
        edit
        remove

Channel
Channels
There are currently no channels.
Add new channel
Change channel order

View
Edit
Remove

自己试试here

分析

  • 我们计算第一个正则表达式以获取以任何字符开头的所有行,然后在“:”之前停止

  • 如果我们有一些空行,我们会删除

  • 我们将结果加入我们的第一部分。

  • 我们计算第二个正则表达式,它将获取所有具有“:”的行的结尾,并带有“:”(每次至少获取一个字符)

  • 我们从每一行中删除“:”,并修剪前导空格

  • 我们加入结果以进行第二部分。

这里是正则表达式:

first part

second part

注意:如果您想在第一部分的每行末尾保留“:”,只需将第一个正则表达式替换为r"(.*):"

【讨论】:

    【解决方案2】:

    只要删除 if 就可以了。

    with open("testFile.yml") as a_file:
        for object in a_file:
            stripped_object = object.rstrip()
            found = False
            file = open("ValuesfileNotTranslated.yml", "a")
            file.writelines(re.split(':|=', stripped_object, maxsplit=1)[-1].strip() + "\n" )
    

    另外,如果你只打开一次文件,解决方案会更有效

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-31
      • 2020-01-22
      • 2012-03-09
      • 1970-01-01
      • 2017-09-09
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多