benjohn / fysh.org wrote:
> Is there a regexp feature that lets me require something to be present
> in the input string for the regexp to match, but for that to not become
> captured as part of the match?
>
> I want this so that I can scan and gsub on a string of code and replace
> variables. Matching just variables requires looking at the context
> arround them, but if I capture this, I replace the context too.
>
> Eg, to scan for variables called x or y, I might use:
>   /(^|[^a-zA-Z])[xy]([^a-zA-Z]|$)/
>
> but using that on "exp(x)" will match (and replace) "(x)", which I don't
> want at all.
>
> Cheers,
>   Benjohn

class String
  def gsub_capture( regexp, replacement )
    offset = 0
    gsub( regexp ){|s|
      offset = $~.offset(1)[0] - $~.offset(0)[0]
      s[ 0, offset ] +
      replacement + s[ offset + $1.size .. -1 ] }
  end
end

puts "1. Take two <2> cups and three <3> spoons".
  gsub_capture( / <(\d)> /,  "x")