问题
The to_yaml method produces nice YAML output, but I would like to include comment lines before some of the elements. Is there a way to do so?
For example, I would like to produce:
# hostname or IP address of client
client: host4.example.com
# hostname or IP address of server
server: 192.168.222.222
From something similar to:
{
:client => 'host4.example.com',
:server => '192.168.222.222',
}.to_yaml
... but am not sure if the YAML module even has a way to accomplish.
UPDATE: I ended up not using the solution which used regexes to insert the comments, since it required the separation of the data from the comments. The easiest and most understandable solution for me is:
require 'yaml'
source = <<SOURCE
# hostname or IP address of client
client: host4.example.com
# hostname or IP address of server
server: 192.168.222.222
SOURCE
conf = YAML::load(source)
puts source
The benefit to me is that nothing is repeated (for example, 'client:' is only specified once), the data and comments are together, the source can be outputted as YAML, and the data structure (available in conf) is available for use.
回答1:
You can do a string replace on all the insertions:
require 'yaml'
source = {
:client => 'host4.example.com',
:server => '192.168.222.222',
}.to_yaml
substitution_list = {
/:client:/ => "# hostname or IP address of client\n:client:",
/:server:/ => "# hostname or IP address of server\n:server:"
}
substitution_list.each do |pattern, replacement|
source.gsub!(pattern, replacement)
end
puts source
output:
---
# hostname or IP address of client
:client: host4.example.com
# hostname or IP address of server
:server: 192.168.222.222
回答2:
Something like this:
my_hash = {a: 444}
y=YAML::Stream.new()
y.add(my_hash)
y.emit("# this is a comment")
Of course, you will need to walk the input hash yourself and either add()
or emit()
as needed.
You could look at the source of the to_yaml
method for a quick start.
回答3:
This isn't perfect (no mid-Array support, for example), but it works for my needs.
def commentify_yaml(db)
ret = []
db.to_yaml(line_width: -1).each_line do |l|
if l.match(/^\s*:c\d+:/)
l = l.sub(/:c(\d+)?:/, '#').
sub(/(^\s*# )["']/, '\1').
sub(/["']\s*$/, '').
gsub(/''(\S+?)''/, "'\\1'").
gsub(/(\S)''/, "\\1'")
end
ret << l.chomp
end
ret * "\n"
end
Example usage.
commentify_yaml(
{
c1: 'Comment line 1',
c2: 'Comment line 2',
'hash_1' => {
c1: 'Foo',
c2: 'Bar',
'key_1' => "Hello!",
},
'baz' => qux,
c3: 'Keep up-numbering the comments in the same hash',
'array_1' => [
1,
2,
3
]
}
)
==>
# Comment line 1
# Comment line 2
hash_1:
# Foo
# Bar
key_1: "Hello!"
baz: "Value of qux"
# Keep up-numbering the comments in the same hash
array_1:
- 1
- 2
- 3
(Note: Syck does not indent arrays they way it arguably should.)
来源:https://stackoverflow.com/questions/14149570/can-rubys-yaml-module-be-used-to-embed-comments