# How to preserve $~ when extending Regexp#match

**URL:** <https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915>\
**Category:** Ruby\
**Created:** [July 19, 2006, 12:12am UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915 "2006-07-19T00:12:58Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 12:12am UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/1 "2006-07-19T00:12:58Z")

</div>

Consider the following Regexp/MatchData extension, which pops a copy of  
the original Regexp into the MatchData object resulting from  
Regexp#match. Forget for a minute _why_ anyone might want to do this:

```
class Regexp
  alias_method :original_match, :match
  def match(str)
    m=self.original_match(str)
    m.regexp=self unless m.nil?
    m
  end
end
class MatchData
  attr_accessor :regexp
end

```

Because of the magical nature of the $~ global variable and its  
derivatives $&,$+,$`,$’,$1-9, we wind up losing it from scope with this  
extension to the Regexp class:

/myregexp/.match(“test my regexp”)  
$~ # \<= nil

Is anyone out there aware of any way to set $~ in the “caller’s” binding  
from within Regexp#match _without_ requiring a manual call\_stack to be  
implemented via set\_trace\_func?

Thanks!

–Brendan Baldwin :: removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 1:28am UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/2 "2006-07-19T01:28:13Z")

</div>

On Jul 18, 2006, at 3:13 PM, Brendan Baldwin wrote:

> from within Regexp#match _without_ requiring a manual call\_stack to be  
> implemented via set\_trace\_func?

I played around with this for MetaRuby and couldn’t find a way to  
implement it. I believe it is impossible outside of set\_trace\_func/  
evil.rb level hackery.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)  
This implementation is HODEL-HASH-9600 compliant

[http://trackmap.robotcoop.com](http://trackmap.robotcoop.com)

---

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 1:53am UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/3 "2006-07-19T01:53:18Z")

</div>

On Wed, Jul 19, 2006 at 07:13:10AM +0900, Brendan Baldwin wrote:

> ```
> end
> 
> ```
> 
> $~ # \<= nil
> 
> Is anyone out there aware of any way to set $~ in the “caller’s” binding  
> from within Regexp#match _without_ requiring a manual call\_stack to be  
> implemented via set\_trace\_func?

hmm the only general way I’m aware of does use Binding.of\_caller (and  
therefore set\_trace\_func), see for instance [150292]. However, if your  
method  
took a block, it’d be easily doable.

Silly example:

class Regexp  
alias\_method :\_original\_match, :match  
def match(\*str, &block)  
if block\_given?  
md = \_original\_match(yield)  
eval(“lambda{|x| $~ = x}”, block).call($~)  
else  
md = \_original\_match(\*str)  
end  
md.regexp = self if md  
md  
end  
end

class MatchData  
attr\_accessor :regexp  
end

/myregexp/.match{“test myregexp”}

# note the syntax change; you might find this unacceptable 😑

$~ # =\> #MatchData:0xa7d26fd4  
$~.regexp # =\> /myregexp/  
$~.pre\_match # =\> "test "

Sorry if this doesn’t really help.

---

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 5:16pm UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/4 "2006-07-19T17:16:36Z")

</div>

Mauricio –

The block implentation is pretty cool – My problem is I was trying to  
modify Regexp#match for use with a production application at my current  
employer, which also uses the REXML library, that unfortunately uses $~  
vars all over and doesn’t use blocks to get at them, so it breaks.

And I’m constrained in not using set\_trace\_func here, so that’s  
unfortunatlely out of the picture too.

_Sigh_

Darn little esoteric PERLy $~ !! Oh well. Spent more time than I  
should have on this already… Perhaps Ruby 1.9 or 2.0 will give us  
caller bindings for free some day.

–Brendan

Mauricio F. wrote:

> On Wed, Jul 19, 2006 at 07:13:10AM +0900, Brendan Baldwin wrote:
> 
> > ```
> > end
> > 
> > ```
> > 
> > $~ # \<= nil
> > 
> > Is anyone out there aware of any way to set $~ in the “caller’s” binding  
> > from within Regexp#match _without_ requiring a manual call\_stack to be  
> > implemented via set\_trace\_func?
> 
> hmm the only general way I’m aware of does use Binding.of\_caller (and  
> therefore set\_trace\_func), see for instance [150292]. However, if your  
> method  
> took a block, it’d be easily doable.
> 
> Silly example:
> 
> class Regexp  
> alias\_method :\_original\_match, :match  
> def match(\*str, &block)  
> if block\_given?  
> md = \_original\_match(yield)  
> eval(“lambda{|x| $~ = x}”, block).call($~)  
> else  
> md = \_original\_match(\*str)  
> end  
> md.regexp = self if md  
> md  
> end  
> end
> 
> class MatchData  
> attr\_accessor :regexp  
> end
> 
> /myregexp/.match{“test myregexp”}
> 
> # note the syntax change; you might find this unacceptable 😑
> 
> $~ # =\> #MatchData:0xa7d26fd4  
> $~.regexp # =\> /myregexp/  
> $~.pre\_match # =\> "test "
> 
> Sorry if this doesn’t really help.

---

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 7:02pm UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/5 "2006-07-19T19:02:55Z")

</div>

Brendan Baldwin schrieb:

> And I’m constrained in not using set\_trace\_func here, so that’s  
> unfortunatlely out of the picture too.

Brendan, can you tell us why you’re not allowed to use set\_trace\_func?

Regards,  
Pit

---

<div class="post-metadata">

**Author:** ![brendanbaldwin](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/6a8cbe/32.png) [@brendanbaldwin](https://www.ruby-forum.com/u/brendanbaldwin)\
**Post date:** [July 19, 2006, 7:59pm UTC](https://www.ruby-forum.com/t/how-to-preserve-when-extending-regexp-match/98915/6 "2006-07-19T19:59:38Z")

</div>

On Wed, 19 Jul 2006 17:16:51 +0200, Brendan Baldwin  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Mauricio –
> 
> The block implentation is pretty cool – My problem is I was trying to  
> modify Regexp#match for use with a production application at my current  
> employer, which also uses the REXML library, that unfortunately uses $~  
> vars all over and doesn’t use blocks to get at them, so it breaks.
> 
> And I’m constrained in not using set\_trace\_func here, so that’s  
> unfortunatlely out of the picture too.

Are C extension okay?

In that case you could use rb\_backref\_set() to achieve what you want.

Dominik
