【问题标题】:Preprocess (populate, generate) files with the content of other files使用其他文件的内容预处理(填充、生成)文件
【发布时间】:2022-02-09 18:08:19
【问题描述】:

我将使用一个有代表性的例子来解释我的问题。

假设我有这两个配置文件:

# product-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical

product_id: general_id
title: general_title
intro: general_intro

.

# service-conf.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical

service_id: general_id
title: general_title
products: list_products

如您所见,前 3 行(配置字段)完全相同。我实际上对这些文件使用 YAML。我想在可维护的文件中包含一些代码,并将它们包含在调用中。我需要一个预处理器来处理这些。比如:

# snippet-seo.file
seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical

.

# product-conf-master.file

@include snippet-seo

product_id: general_id
title: general_title
intro: general_intro

.

# service-conf-master.file

@include snippet-seo

service_id: general_id
title: general_title
products: list_products

预处理器将读取/masters/*中的所有主文件,处理所有调用并将它们替换为来自/snippets/的适当sn-p并将结果保存在/

我正在使用@ 进行通话,但我可以选择适合所选预处理器的任何其他格式。我使用这种方式是因为它非常类似于 SASS 指令 @extend@include

我可以实现这一目标的最佳和最简单的方法是什么? node 的包是我的首选。

【问题讨论】:

  • 您是否考虑过使用合并密钥工具将文件组合成一个组合 YAML 文件来定义公共部分并直接使用它(区分在顶级名称上使用什么)或写出不同的 YAML来自这个组合的文件?
  • 是的,这可能会有所帮助。有了您的输入,我现在已经能够找到有关此的更多信息(yaml.org/type/merge.html)但是,我仍然不知道使用什么来预处理(合并)这些文件。这些文件的使用者需要处理的文件。就像浏览器需要 CSS 而不是 SASS 来透视一样。
  • 对于预处理,您需要使用一些通用模板。但是,如果您使用合并键和单个源 YAML,则可以使用几行 Python 代码轻松拆分该源。

标签: node.js npm yaml preprocessor populate


【解决方案1】:

如果您不一定需要对文件进行预处理,您可以使用小型 YAML 处理程序来解决这个问题(您可能可以使用一些基于节点的编程来做到这一点)。

import pathlib
import ruamel.yaml

yaml = ruamel.yaml.YAML()
master = pathlib.Path('master.file')
data = yaml.load(master))

common = data['common']
for file_name in data:
    if file_name == 'common':
        continue
    data_out = ruamel.yaml.comments.CommentedMap()
    # you can leave out the following two lines of code if you do a safe_load()
    # but you will lose the ordering in your output file
    for k, v in common.items():
        data_out[k] = v
    for k, v in data[file_name].items():
        data_out[k] = v
    with open(file_name, 'wb') as fp:
        yaml.dump(data_out, stream=fp)

鉴于文件master.file中的以下输入:

# YAML master file
common: &COMMON
  seo_title: general_title
  seo_description: seo_description
  seo_canonical: seo_canonical

product-conf.file:
  <<: *COMMON
  product_id: general_id
  title: general_title
  intro: general_intro

service-conf.file:
  <<: *COMMON
  service_id: general_id
  title: general_title
  products: list_products

运行程序会给你两个文件,product-conf.file::

seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
product_id: general_id
title: general_title
intro: general_intro

service-conf.file:

seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical
service_id: general_id
title: general_title
products: list_products

也可以将这三个部分放在单独的输入文件中,而不是将值放在一个组合文件中。


或者,如果您的真实输入文件不包含cpp 以特殊方式处理的任何内容,您可以这样做:

cpp -P -include master.in -o service-conf.file service-conf.in

master.in:

seo_title: general_title
seo_description: seo_description
seo_canonical: seo_canonical

service-conf.in:

service_id: general_id
title: general_title
products: list_products

这给出了与前面示例相同的service-conf.outproduct-conf.in 当然会以同样的方式工作。

cpp-P 选项抑制调试输出 cmets,-include 包含参数,就好像输入文件的第一行具有预处理器指令一样:

#include "master.in"

您也可以明确说明并省略命令行选项。

【讨论】:

  • 谢谢@anthon!当我实施解决方案时,我会在这里回答自己。 (不能投票,因为我没有足够的声誉......)
猜你喜欢
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2011-03-19
  • 2021-05-12
  • 1970-01-01
相关资源
最近更新 更多