使用其他文件的内容预处理(填充、生成)文件

Preprocess (populate, generate) files with the content of other files

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

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

# 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/ 中的适当片段并将结果保存在 /

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

实现此目标的最佳和最简单方法是什么?节点包将是我的第一选择。

如果您不一定需要预处理文件,您可以使用小型 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 选项抑制调试输出注释,-include 包含参数,就好像输入文件的第一行有预处理程序指令一样:

#include "master.in"

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