Parsing key/value pairs in ruby

608 views
Skip to first unread message

Patrick Mohr

unread,
Aug 12, 2010, 12:33:24 AM8/12/10
to puppet...@googlegroups.com
I'm making a provider for cups and I need to parse a string into arbitrary key/value pairs. The string looks like this:

printer-make-and-model='Brother HL-2060 Foomatic/hpijs-pcl5e (recommended)' printer-state=3 printer-state-change-time=1266621145 printer-state-reasons=none printer-type=8564756

I know almost no ruby. Any advice for what functions or data structures I want to use? It looks like "split" might be what I want to use for parsing, but the quoted strings will give me trouble. For the first version, I'm only using 3 of the values. Do I just want to pull out those manually instead of parsing the whole string?

John Warburton

unread,
Aug 12, 2010, 2:48:22 AM8/12/10
to puppet...@googlegroups.com
I based my bad first ruby code on http://www.devco.net/archives/2008/04/17/easy_per-machine_custom_facts_
for_puppet.php

I just checked the URL, and Volcane admits the code was bad too - so have a look at http://www.devco.net/archives/2008/06/16/rework_of_puppet_facts_for_etcfactstxt.php

John


--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.




--
John Warburton
Ph: 0417 299 600
Email: jwarb...@gmail.com

Paul Nasrat

unread,
Aug 12, 2010, 9:45:52 AM8/12/10
to puppet...@googlegroups.com

You might use shellwords to handle the quoting.

>> require 'shellwords'
>> l = %q(printer-make-and-model='Brother HL-2060 Foomatic/hpijs-pcl5e (recommended)' printer-state=3 printer-state-change-time=1266621145 printer-state-reasons=none printer-type=8564756)
>> Shellwords.shellwords(l)
=> ["printer-make-and-model=Brother HL-2060 Foomatic/hpijs-pcl5e
(recommended)", "printer-state=3",
"printer-state-change-time=1266621145", "printer-state-reasons=none",
"printer-type=8564756"]

Paul

Rein Henrichs

unread,
Aug 12, 2010, 1:55:32 PM8/12/10
to puppet-users
Excerpts from Paul Nasrat's message of Thu Aug 12 06:45:52 -0700 2010:

> You might use shellwords to handle the quoting.
>
> >> require 'shellwords'
> >> l = %q(printer-make-and-model='Brother HL-2060 Foomatic/hpijs-pcl5e (recommended)' printer-state=3 printer-state-change-time=1266621145 printer-state-reasons=none printer-type=8564756)
> >> Shellwords.shellwords(l)
> => ["printer-make-and-model=Brother HL-2060 Foomatic/hpijs-pcl5e
> (recommended)", "printer-state=3",
> "printer-state-change-time=1266621145", "printer-state-reasons=none",
> "printer-type=8564756"]
>
> Paul

Paul, shellwords.rb is one of the many great but little-known Ruby
standard library tools. Going a little further, we can turn a string of
shell-quoted key/value pairs separated by an '=' into a hash using:

require 'shellwords'

shellwords = Shellwords.shellwords(your_string)
pairs = shellwords.map{ |s| s.split('=', 2) }.flatten
Hash[*pairs]

This may be a little daunting, so let's break it down:

1) shellwords = Shellwords.shellwords(your_string) turns the string into
an array of tokens, assuming it's been assigned to your_string.

2) pairs.map{|s| s.split('=', 2)} takes each string in turn and splits
it on the first '=', returning a new array containing arrays of
[before-the-equals, after-the-equals] pairs. Splitting on the first '='
avoids any possible bugs where there is an = in the value.

3) .flatten flattens this array of arrays into an array that looks like [ key, value,
key, value, ... ]. We'll need this for step 4.

4) Hash[1, 2, 3, 4] turns the arguments into a hash: { 1 => 2, 3 => 4 }.
We use this to turn the array above into a Hash. The * is used to
turn the array into a series of arguments, because Hash[[1,2,3,4]]
doesn't work, but Hash[*[1,2,3,4]] does. (I often think of * in this
context as the "unary unarray operator".)
--

Rein Henrichs
http://puppetlabs.com

There are two types of Linux developers - those who can spell, and
those who can't. There is a constant pitched battle between the two.
(From one of the post-1.1.54 kernel update messages posted to c.o.l.a)

Patrick Mohr

unread,
Aug 12, 2010, 4:24:29 PM8/12/10
to puppet...@googlegroups.com

Thanks both of you for the help. It looks like this will do 40% of the work for me.

Reply all
Reply to author
Forward
0 new messages