2

I'm trying to match all text in the block:

group :development do
  gem 'test'
end

In the context above, I want to return "gem 'test'". What I'm using is:

/(?<=group :development do)(.*)(?=end)/m

Why doesn't it work?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Alex Takitani
  • 491
  • 5
  • 14

1 Answers1

4

I'm not exactly sure why, but changing the .* to .*? allows this to match.

Rubular: http://www.rubular.com/r/GaQj6cM0rk

It seems like it should match fine with .* as well, but for some reason it doesn't appear to be backtracking.

Here is the Rubular when .* is used instead: http://www.rubular.com/r/jKf0bDZi7T

Note that regardless of the reason for this behavior, you should be using .*? anyway, otherwise you would only find a single match from the beginning of the first block to the end of the last block (if there were multiple blocks in a string).

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • 1
    `.*` searches for the longest possible match. `.*?` searches for the shortest possible and is preferable under most circumstances. – tadman Mar 05 '13 at 20:47
  • It's because `.*` is a "greedy match", which matches as much as possible, and in this case eats the `end` as well, whereas `.*?` is a non-greedy match and will only eat enough to allow the rest of the regex to match. – Jim Stewart Mar 05 '13 at 20:47
  • 2
    To the above comments, `.*` should also match in this example. See http://regexr.com?34100. Even though the `.*` will eat the `end`, the regex engine should backtrack until the match succeeds. – Andrew Clark Mar 05 '13 at 20:51
  • I've just tried to reproduce this with `/(?<=f).*/` vs. `/(?<=fo).*/` to match `foo` - the latter failed in Rubular, and when I reopened the page in Rubular, the `o` had spontaneously changed into a `0`!! I'm going to investigate further. – Tim Pietzcker Mar 05 '13 at 20:56
  • @TimPietzcker Keep me updated! I am really curious about this behavior. – Andrew Clark Mar 05 '13 at 20:57