用字符串化的JSON替换YAML中的字符串

时间:2019-01-23 21:00:16

标签: bash

假设您有一个模板YAML文件:

foo:
  bar: {%VARIABLE%}

,并希望bar的值是字符串化的JSON?例如:

foo:
  bar: '{ "hey": "there" }'

就我而言,JSON位于文件中,因此我正在这样做:

VAR=$(cat my.json)
sed -i '' "s|{%VARIABLE%}|'$VAR'|g" foo.yaml

但是如果您将换行符保留在JSON中,sed会抱怨。

如果我使用cat my.json | tr -d '\n'删除换行符,则提取我的JSON的程序会显示JSON中的私钥无效。

执行此操作的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

我建议改用perl,它比sed更健壮,并且还可以编写一些单行代码,例如:

VAR=$(<my.json)
perl -i.bak -wpe "s|{%VARIABLE%}|'$VAR'|g" foo.yaml

经过下面的文件my.json的测试

{ "hey" : "there",
  "status" : "ok" }

最后,请注意,如果.json文件包含$和@之类的字符,它们在替换字符串中可能具有特殊含义,那么值得依靠Perl的引用运算符q{}

perl -i.bak -wpe "my \$x=q{$VAR}; s|{%VARIABLE%}|'\$x'|g" foo.yaml

或者:

perl -i.bak -wpe "my \$x='$VAR'; s|{%VARIABLE%}|'\$x'|g" foo.yaml

答案 1 :(得分:1)

您所拥有的没有YAML文件,甚至没有模板YAML文件, 因为这是无效的YAML,所以:(流)映射开始指示符def customer_profiles(country, name): print("{},{}".format(name, country)) customer_profiles(**{"gender" : "male", "name" : "David" , "country" : "USA"}) 后没有 键值对。

您所拥有的是一个YAML文件的模板,该模板使用 jinja2模板,并且有Traceback (most recent call last): File "luggage.py", line 12, in <module> customer_profiles(**{"gender" : "male", "name" : "David" , "country" : "USA"}) TypeError: customer_profiles() got an unexpected keyword argument 'gender' 的插件可用于 完全更新那种模板(实际上通常要多一些) 比您的复杂)。该插件将模板转换为有效的YAML 文件,然后可以使用Python安全地加载,更新和转储文件。

它的主要优点是可以将值节点设置为表示为 文字样式标量,并且无论哪种JSON都没有问题 扔掉它,因为您的字符串化JSON至少需要转义 的引号(使用双引号时还可以使用反斜杠)。

{

给出:

ruamel.yaml

通常,模板的non-jinja2部分被编辑为YAML,在您需要使用import sys import ruamel.yaml yaml_str = """\ foo: bar: {%VARIABLE%} """ json_str = """\ { "hey": "there's cake" } """ yaml = ruamel.yaml.YAML(typ='jinja2') data = yaml.load(yaml_str) data['foo']['bar'] = ruamel.yaml.scalarstring.LiteralScalarString(json_str) del data['foo'].ca._items['bar'] yaml.dump(data, sys.stdout) 的情况下, 否则,%VARIABLE%将会显示在输出中的注释中。

我故意更改了JSON中的值以包含单引号。将其包括在您的示例中 您需要执行的输出:

foo:
  bar: |
    {
      "hey": "there's cake"
    }

尽管使用不支持YAML的工具(例如 del,正确处理空行的多行JSON否 不重要的。通过将元素插入为 文字样式标量,但这必须使用适当的解析器来完成, 那样可以例如遇到第一行时采取适当的措施 缩进量小于第二个缩进量的JSON,等等。