Ian
Ian

Reputation: 21

Create a regular expression to match YAML keys in Ruby

Based on the following data in a YAML file, is it possible to create a regular expression in Ruby which matches the respective Group and Item keys from a list

Source Data

Groups:
    GroupA:
    - item 1
    - item 3
    Group B:
    - itemA
    - item 3
    C:
    - 1
    - item 3

Test String:

GroupA item 1     
Group B itemA
c item 1
C 1
GroupA 1

Expected Match Groups

Match 1:
   1. GroupA
   2. item 1
Match 2:
   1. Group B
   2. itemA
Match 3:
   1. C
   2. 1

Thanks for any help!

Ian

================================== Update: Following Tin Mans comment -

Here's some further background...

A class inside a plugin exists which contains a number of methods. Each method receives a string which is parsed to determine what action is performed. In some methods, the contents of the string are used in the subsequent actions - when this is required a regular expression is used to extract (or match) the relevant parts of the string. Unfortunately there is no control over the upstream code to alter this process.

In this case, the string is in the form "Group Item Status". However the group and item names are not necessarily single words and each group does not have to contain all items. e.g.

"Group A Item 1"
"c item 1"
"GroupA 1"

So, what's needed is a method of parsing the input string to get the respective Group and Item so that the correct values are passed to methods further down the line. Given that other comparable methods in the class use regular expressions, and there is a YAML file which contains the definitive list of group - item pairs, a regular expression was my first line of thought.

However, I am open to better approaches

Many thanks

Ian

Upvotes: 2

Views: 4062

Answers (1)

the Tin Man
the Tin Man

Reputation: 160551

Why would you want to match anything in a YAML file? Load it into Ruby using the YAML parser, and search it, or modify in memory.

If you want to save the modified file, the YAML parser can emit a Ruby object as YAML, which you then save.

require 'yaml'

yaml = '
---
Groups:
    GroupA:
    - item 1
    - item 3
    Group B:
    - itemA
    - item 3
    C:
    - 1
    - item 3
'

yaml = YAML.load(yaml)
# => {"Groups"=>{"GroupA"=>["item 1", "item 3"], "Group B"=>["itemA", "item 3"], "C"=>[1, "item 3"]}}

yaml['Groups']['GroupA'].first
# => "item 1"

yaml['Groups']['Group B'][1]
# => "item 3"

yaml['Groups']['C'].last
# => "item 3"

Based on the above definitions, manipulating the data could be done like this:

yaml = YAML.load(yaml)
groups = yaml['Groups']

new_group = {
  'groupa_first' => groups['GroupA'].first,
  'groupb_second' => groups['Group B'][1],
  'groupc_last' => groups['C'].last
}
yaml['New Group'] = new_group

puts yaml.to_yaml

Which outputs:

---
Groups:
  GroupA:
  - item 1
  - item 3
  Group B:
  - itemA
  - item 3
  C:
  - 1
  - item 3
New Group:
  groupa_first: item 1
  groupb_second: item 3
  groupc_last: item 3

There's a reason we have YAML parsers for all the different languages; They make it easy to load and use the data. Take advantage of that tool, and use Ruby to modify the data, and, if needed, write it out again. It would be one huge YAML file before I'd even think of trying to modify it on disk considering it's so easy to do in memory.

Now, the question becomes, how do you search the keys of a hash using a regex?

yaml['Groups'].select{ |k,v| k[/^Group/] }
# => {"GroupA"=>["item 1", "item 3"], "Group B"=>["itemA", "item 3"]}

Once you have the ones you want, you can easily modify their contents, substitute them back into the in-memory hash, and write it out.

Upvotes: 4

Related Questions