32

I'm trying to use a named capture group inside a block in Ruby. $1 still works, but I'd like to reference it using the name I gave.

"foo /(bar)".gsub(/(?<my_word> \(.*?\) )/x) do |match|
  puts "$1 = #{$1} and $my_word = #{$my_word}"
end

Expected:$1 = (bar) and $my_word = (bar)

Chris
  • 2,174
  • 28
  • 37

1 Answers1

46

You are looking for

"foo /(bar)".gsub(/(?<my_word> \(.*?\) )/x) do |match|
  puts "$1 = #{$1} and $my_word = #{$~[:my_word]}"
end
oldergod
  • 15,033
  • 7
  • 62
  • 88
  • 2
    Excellent, thank you. I've never seen anything like that syntax before. – Chris May 16 '13 at 05:27
  • Can you give me a good Regex tutorial link? I know `zero` about `regex`. :( – Arup Rakshit May 16 '13 at 06:57
  • Is there a reason you need the `?` in `\(.*?\)`? In my understanding, that's saying "zero or more of any character, zero or more times," which seems the same as just "zero or more of any character," i.e. `\(.*\)` – acobster Oct 31 '13 at 06:23
  • @acobster the interrogation point `?` is a modifier of the star: it makes it a non-greedy operator, so it will end on the first occurrence of the following expression. But I just copied paste the OP's code so you should ask him :) – oldergod Nov 01 '13 at 05:44
  • 1
    @acobster It's been a while since I wrote this, but I believe it was to keep it from capturing stuff in parentheses following the first pair. i.e., the 'bar' in `(foo)(bar)`. If it was greedy, it would start at the far left and capture everything up to the last parentheses. – Chris Dec 20 '13 at 08:14
  • 3
    the `$~` is equivalent to `Regexp.last_match` – pgericson Mar 26 '18 at 14:25