Sean
Sean

Reputation: 1098

ruby regex with variable optionals

I am having trouble figuring out the best way to parse a particular set of strings.

some examples of strings I will come accross are:

str = 'name[key1][key2][key3]'
str2 = 'name[key1]'
str3 = 'name'

Here are the respective arrays i'm hoping to get out of the strings:

arr1 = ['name', 'key1', 'key2', 'key3']
arr2 = ['name', 'key1']
arr3 = ['name']

So as you can see, the key is optional and can be a variable count.

The closest i've been able to come is this:

>> str = 'name[key1][key2][key3]'
"name[key1][key2][key3]"

>> str.scan(/(.+?)(\[.+?\])/)
[["name", "[key1]"], ["[key2]", "[key3]"]]

So, I can always do a flatten on that array, and then a gsub to get rid of brackets, but I don't want to just hack it together. I would like to be able to get it done in one shot. I considered just doing a string split at the bracket, but that also seems a bit of a bandaid approach as well. If anyone has ideas on how I can accomplish this better than regex, or how I can accomplish this correctly with the methods i'm using, that would be great!

Upvotes: 1

Views: 52

Answers (4)

Sharang Dashputre
Sharang Dashputre

Reputation: 111

This will work for you:

str.tr('[]', '  ').split

Changes both '[' and ']' to ' ' and then splits on ' '

If the number of characters you need to change to ' ' increases change the tr() to gsub() and modify the arguments accordingly

Upvotes: 0

Sabuj Hassan
Sabuj Hassan

Reputation: 39365

Using split??

str = 'name[key1][key2][key3]'
print str.split(/[\[\]]+/)

Upvotes: 0

Justin Ko
Justin Ko

Reputation: 46836

You could use scan and ignore the brackets:

str = 'name[key1][key2][key3]'
p str.scan(/[^\[\]]+/)
#=> ["name", "key1", "key2", "key3"]

str2 = 'name[key1]'
p str2.scan(/[^\[\]]+/)
#=> ["name", "key1"]

str3 = 'name'
p str3.scan(/[^\[\]]+/)
#=> ["name"]

Upvotes: 1

Daniël Knippers
Daniël Knippers

Reputation: 3055

You could use positive lookahead / lookbehind to look for brackets to possibly exist, but exclude them from the match. Then you do not have to use gsub or flatten at all:

str = 'name[key1][key2][key3]'
p str.scan(/(?<=\[)?\w+(?=\])?/)
# => ["name", "key1", "key2", "key3"]

Read more about the Regexp class in the Ruby Docs.

Upvotes: 0

Related Questions