将YAML与变量一起使用


82

YAML文件中的变量可能吗?例如:

theme:
  name: default
  css_path: compiled/themes/$theme.name
  layout_path: themes/$theme.name

在此示例中,如何theme: name: default在其他设置中使用?语法是什么?


您使用什么语言/库来解析此YAML?在YAML中没有标准的方法可以执行此操作,但是您的库可能有一些技巧。
杰西·贝德


@CiroSantilli巴拿马文件六四事件法轮功;; 密切相关,但不可重复。标准YAML不支持任意变量,但是可以从YAML解析树中对整个元素进行交叉引用。因此,问题略有不同。
dreftymac


Answers:


106

我有同样的问题,经过大量研究,看来这是不可能的

来自cgat的答案是在正确的轨道上,但是您实际上不能将这样的引用串联起来。

您可以使用YAML中的“变量”来做这些事情(在设置变量时将它们正式称为“节点锚”,在以后使用它们时将其称为“引用”):

定义一个值,并在以后使用它的精确副本:

default: &default_title This Post Has No Title
title: *default_title

{ 要么 }

example_post: &example
  title: My mom likes roosters
  body: Seriously, she does. And I don't know when it started.
  date: 8/18/2012
first_post: *example
second_post:
  title: whatever, etc.

有关更多信息,请参见有关YAML的Wiki页面的此部分: http : //en.wikipedia.org/wiki/YAML#References

定义一个对象,并在以后的修改中使用它:

default: &DEFAULT
  URL:          stooges.com
  throw_pies?:  true  
  stooges:  &stooge_list
    larry:  first_stooge
    moe:    second_stooge
    curly:  third_stooge

development:
  <<: *DEFAULT
  URL:      stooges.local
  stooges: 
    shemp: fourth_stooge

test:
  <<: *DEFAULT
  URL:    test.stooges.qa
  stooges: 
    <<: *stooge_list
    shemp: fourth_stooge

这是直接从一个很棒的演示中获取的: https //gist.github.com/bowsersenior/979804


1
此外,这个问题本质上是一个重复:stackoverflow.com/questions/2063616/...
benrugg

1
怎么<<办?我似乎在文档中找不到它。
Hi-Angel

1
@ Hi-Angel YAML合并密钥规范回答了问题,该怎么<<做?
dreftymac

46

经过一番搜索,我发现可以使用%运算符的更清洁的解决方案。

在您的YAML文件中:

key : 'This is the foobar var : %{foobar}'

在您的红宝石代码中:

require 'yaml'

file = YAML.load_file('your_file.yml')

foobar = 'Hello World !'
content = file['key']
modified_content = content % { :foobar => foobar }

puts modified_content

输出为:

This is the foobar var : Hello World !

正如@jschorr在评论中所说,您还可以将多个变量添加到Yaml文件中的值:

Yaml:

key : 'The foo var is %{foo} and the bar var is %{bar} !'

红宝石:

# ...
foo = 'FOO'
bar = 'BAR'
# ...
modified_content = content % { :foo => foo, :bar => bar }

输出:

The foo var is FOO and the bar var is BAR !

1
很棒的发现;令人高兴的是,您还可以执行多个变量:%{var1:'whatever',var2:'anotherone'}。
jschorr 2014年

2
阅读有关%Ruby字符串运算符的更多信息:ruby-doc.org/core-2.2.3/String.html#method-i-25
Trantor Liu

另一种方法是加载yaml,这将为您提供ruby中的哈希值。可以对哈希进行更改,然后将其写回到文件中。
leoOrion

好东西。还可以与ReactJS + Webpack + messageformat-loader + react-message-context + YAML解决方案一起使用。它实际上开箱即用,可以使用变量作为道具:<Message id = {'textId'} foo = {'some text'} />
Arkadiusz Lendzian

3

这是一篇旧文章,但是我有类似的需求,这是我想出的解决方案。这有点骇人听闻,但它可以并且可以改进。

require 'erb'
require 'yaml'

doc = <<-EOF
  theme:
  name: default
  css_path: compiled/themes/<%= data['theme']['name'] %>
  layout_path: themes/<%= data['theme']['name'] %>
  image_path: <%= data['theme']['css_path'] %>/images
  recursive_path: <%= data['theme']['image_path'] %>/plus/one/more
EOF

data = YAML::load("---" + doc)

template = ERB.new(data.to_yaml);
str = template.result(binding)
while /<%=.*%>/.match(str) != nil
  str = ERB.new(str).result(binding)
end

puts str

一个很大的缺点是它在yaml文档中内置了一个可能存在或可能不存在的变量名(在本例中为“数据”)。也许更好的解决方案是使用$,然后在ERB之前用Ruby中的变量名替换它。而且,仅使用hashes2ostruct进行测试,该方法允许使用data.theme.name类型表示法,这在外观上要容易得多。所需要做的就是用此包装YAML :: load

data = hashes2ostruct(YAML::load("---" + doc))

然后您的YAML文档可以如下所示

doc = <<-EOF
  theme:
  name: default
  css_path: compiled/themes/<%= data.theme.name %>
  layout_path: themes/<%= data.theme.name %>
  image_path: <%= data.theme.css_path %>/images
  recursive_path: <%= data.theme.image_path %>/plus/one/more
EOF

0

Rails / ruby​​框架能够做一些模板工作...经常用于加载环境变量...

# fooz.yml
  foo:
    bar: <%= $ENV[:some_var] %>

不知道这是否适用于javascript框架,因为我认为YML格式是json的超集,它取决于为您读取yml文件的方式。

如果您可以根据自己的读者使用类似的模板,或<< >>{{ }}样式,则只需...

在另一个yml文件中...

# boo.yml

development:
  fooz: foo

这样一来,您基本上就可以在每次动态设置的原始文件中插入一个变量作为参考。在阅读时,我还看到您可以动态地创建或打开YML文件作为多种语言的对象,这使您可以创建文件并链式编写一系列YML文件,或者只是将它们全部静态地指向动态创建的文件。


0

如果您的需求就像解析替换多个变量,然后将其用作哈希/或其他任何东西,那么您可以执行以下操作

require 'yaml'
require 'json'
yaml = YAML.load_file("xxxx.yaml")
blueprint = yaml.to_json % { var_a: "xxxx", var_b: "xxxx"}
hash = JSON.parse(blueprint)

在yaml内,只需将这样的变量

"%{var_a}"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.