Ruby: Write Escaped String to Yaml

Ruby: Write escaped string to YAML

If you want to store an escaped string in YAML,
escape it using #inspect before you convert it to YAML:

irb> require 'yaml'
=> true
irb> str = %{This string's a little complicated, but it "does the job" (man, I hate scare quotes)}
=> "This string's a little complicated, but it \"does the job\" (man, I hate scare quotes)"
irb> puts str
This string's a little complicated, but it "does the job" (man, I hate scare quotes)
=> nil
irb> puts str.inspect
"This string's a little complicated, but it \"does the job\" (man, I hate scare quotes)"
=> nil
irb> puts str.to_yaml
--- This string's a little complicated, but it "does the job" (man, I hate scare quotes)
=> nil
irb> puts str.inspect.to_yaml
--- "\"This string's a little complicated, but it \\\"does the job\\\" (man, I hate scare quotes)\""
=> nil

YAML doesn't quote strings unless it has to. It quotes strings if they include things that it would miss if it stored it unquoted - like surrounding quote characters or trailing or leading spaces:

irb> puts (str + " ").to_yaml
--- "This string's a little complicated, but it \"does the job\" (man, I hate scare quotes) "
=> nil
irb> puts %{"#{str}"}.to_yaml
--- "\"This string's a little complicated, but it \"does the job\" (man, I hate scare quotes)\""
=> nil
irb> puts (" " + str).to_yaml
--- " This string's a little complicated, but it \"does the job\" (man, I hate scare quotes)"
=> nil

However, as a YAML consumer, whether the string is quoted shouldn't matter to you. You should never be parsing the YAML text yourself - leave that to the libraries. If you need the string to be quoted in the YAML file, that smells bad to me.

It doesn't matter whether your strings have '&'s in them, YAML will preserve the string:

irb> test = "I'm a b&d string"
=> "I'm a b&d string"
irb> YAML::load(YAML::dump(test))
=> "I'm a b&d string"
irb> YAML::load(YAML::dump(test)) == test
=> true

How can I escape % characters in YAML?

Try %% it might work to escape.

how to escape a single quote (onwer's) in yaml file

If you have an actual regular expression: (shortened for brevity)

re = /owner's PID (?<tid>[\d]+)/
#=> /owner's PID (?<tid>[\d]+)/

You can get its string representation via source:

re.source
#=> "owner's PID (?<tid>[\\d]+)"

This can be used in YAML:

require 'yaml'
yaml = { 'pattern' => re.source }.to_yaml
#=> "---\npattern: owner's PID (?<tid>[\\d]+)\n"

puts yaml

Output:

---
pattern: owner's PID (?<tid>[\d]+)

To parse it:

hash = YAML.load(yaml)
#=> {"pattern"=>"owner's PID (?<tid>[\\d]+)"}

And a regular expression can be created via:

Regexp.new(hash['pattern'])
#=> /owner's PID (?<tid>[\d]+)/

Note that Regexp#source doesn't retain the regexp's options. You might have to store them separately via Regexp#options.

How do I declare a string with both single and double quotes in YAML?

escaping should be done like this

"When you're using double quotes, they look like \"this\""

YAML: error parsing a string with escaped double quote

Your problem is that heredocs act like double quoted strings as far as escaping is concerned. That means that a \" in your heredoc ends up as just " in your string. Observe:

>> data_ =<<END_
description: "Acme acquires ILM: Lucas says \"Inevitable!\""
END_
>> puts data_
description: "Acme acquires ILM: Lucas says "Inevitable!""

You want to get a \ into the YAML string so you'll have to escape it:

data_ =<<END_
description: "Acme acquires ILM: Lucas says \\"Inevitable!\\""
END_

Alternatively, use %q{...} to quote your string so that it behaves more like a single quoted string:

data_ = %q{
description: "Acme acquires ILM: Lucas says \"Inevitable!\""
}

Best way to escape and unescape strings in Ruby?

Ruby 2.5 added String#undump as a complement to String#dump:

$ irb
irb(main):001:0> dumped_newline = "\n".dump
=> "\"\\n\""
irb(main):002:0> undumped_newline = dumped_newline.undump
=> "\n"

With it:

def escape(s)
s.dump[1..-2]
end

def unescape(s)
"\"#{s}\"".undump
end

$irb
irb(main):001:0> escape("\n \" \\")
=> "\\n \\\" \\\\"
irb(main):002:0> unescape("\\n \\\" \\\\")
=> "\n \" \\"

Ruby to_yaml utf8 string

This is probably a really bad idea as I'm sure YAML has its reasons for encoding the characters as it does, but it doesn't seem too hard to undo:

require 'yaml'
require 'yaml/encoding'

text = "Ça va bien?"

puts text.to_yaml(:Encoding => :Utf8) # => --- "\xC3\x87a va bien?"
puts YAML.unescape(YAML.dump(text)) # => --- "Ça va bien?"


Related Topics



Leave a reply



Submit