Ruby regex to match multiple occurrences of a pattern

I'm looking to create a ruby ​​regex to match multiple occurrences of a pattern and return them to an array. The template is simple: [[. +]]. That is, two left brackets, one or more characters, and then two right brackets.

This is what I did:

str = "Some random text[[lead:first_name]] and more stuff [[client:last_name]]"
str.match(/\[\[(.+)\]\]/).captures

      

The regex above doesn't work because it returns this:

["lead:first_name]] and another [[client:last_name"]

      

When I wanted it was the following:

["lead:first_name", "client:last_name"] 

      

I thought that if I used a group without registration, then for sure it should solve the problem:

str.match(/(?:\[\[(.+)\]\])+/).captures

      

But the uncaptured group returns the same exact wrong conclusion. Any idea on how I can solve my problem?

+3


source to share


2 answers


Try this

:

 => str.match(/\[\[(.*)\]\].*\[\[(.*)\]\]/).captures
 => ["lead:first_name", "client:last_name"] 

      



With many occurrences

:

 => str
 => "Some [[lead:first_name]] random text[[lead:first_name]] and more [[lead:first_name]] stuff [[client:last_name]]" 
 => str.scan(/\[(\w+:\w+)\]/)
 => [["lead:first_name"], ["lead:first_name"], ["lead:first_name"], ["client:last_name"]] 

      

+3


source


The problem with your regex is that the portion .+

is "greedy", which means that if the regex matches both less and most of the string, it will grab most of it ( more about greedy regex ).

In Ruby (and most regex syntaxes), you can qualify your quantifier +

with ?

to make it non-living. This way your regex will become /(?:\[\[(.+?)\]\])+/

.



However, you will notice that this still does not work for what you want to do. Ruby capture groups just don't work inside a repeating group. For your problem, you need to use scan

:

"[[a]][[ab]][[abc]]".scan(/\[\[(.+?)\]\]/).flatten
    => ["a", "ab", "abc"]

      

+6


source







All Articles