# Gsub wrapper

**URL:** <https://www.ruby-forum.com/t/gsub-wrapper/76007>\
**Category:** Ruby\
**Created:** [March 3, 2006, 12:09am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007 "2006-03-03T00:09:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 12:09am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/1 "2006-03-03T00:09:19Z")

</div>

Help!

How do I get $1, $2, and $3 to get interpolated in the following  
snippet?

string = ‘This is a test of the emergency’  
regexp = Regexp.new(’(\W)+(\w\w)(\W)+’)  
replacement = ‘$1-\>$2\<-$3’  
user\_wants\_upcase=FALSE

# Note: All variables above are set by the user of the program, so I

don’t know

# what they will contain before runtime.

string.gsub!(regexp) {  
return\_value = string # Here, how do I get $1, $2, and $3 to  
interpolate?

if (user\_wants\_uppercase)  
return\_value.upcase! || return\_value  
end

return\_value  
}

I want return\_value to be -\> ‘This -\>is\<- a test -\>of\<- the emergency’

Note: I know that I can get it to work with the non-block version of  
gsub! but I need to use the block version.

Thanks

Hector

---

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 12:24am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/2 "2006-03-03T00:24:24Z")

</div>

Hector wrote:

> Help!
> 
> How do I get $1, $2, and $3 to get interpolated in the following  
> snippet?
> 
> string = ‘This is a test of the emergency’  
> regexp = Regexp.new(’(\W)+(\w\w)(\W)+’)  
> replacement = ‘$1-\>$2\<-$3’

If you have ‘"#{$1}-\>#{$2}\<-#{$3}"’, you can eval  
it in the block. This is probably a bad idea, though.

To make this a bit safer, you would probably want the  
user to give you some kind of a sprintf-style string  
that you format inside the block. This might limit  
the user to strictly linear numbering or something.

> user\_wants\_upcase=FALSE
> 
> # Note: All variables above are set by the user of the program, so I
> 
> don’t know
> 
> # what they will contain before runtime.
> 
> string.gsub!(regexp) {  
> return\_value = string # Here, how do I get $1, $2, and $3 to  
> interpolate?
> 
> if (user\_wants\_uppercase)  
> return\_value.upcase! || return\_value  
> end
> 
> return\_value  
> }
> 
> I want return\_value to be -\> ‘This -\>is\<- a test -\>of\<- the emergency’
> 
> Note: I know that I can get it to work with the non-block version of  
> gsub! but I need to use the block version.
> 
> Thanks
> 
> Hector

E

---

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 12:30am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/3 "2006-03-03T00:30:13Z")

</div>

On Mar 2, 2006, at 6:09 PM, Hector wrote:

> # Note: All variables above are set by the user of the program, so I
> 
> Hector
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

assuming I understand your question:

str = “#{$1}-\>#{$2}\<-#{$3}”

Alternatively:

str = “#$1-\>#$2\<-#$3”

---

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 3:30am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/4 "2006-03-03T03:30:37Z")

</div>

Timothy G. wrote:

> str = “We love Ruby”  
> puts str.gsub(/We (\w+) \w+/, ‘Why do we \1 it?’)  
> puts str.gsub(/(\w+)$/, “it because \1 allows us to do cool stuff!”)

First, thanks to everyone for your input.

But I wanted to be able to invoke ‘gsub’ with end-user specified strings  
for both the regex pattern and the replacement string. If the end-user  
regex patern contains regexp groupings and the replacement string  
contains any of $1, $2, … $9, these variables($1,$2…) will not get  
interpolated because they are within a string object. The non-block  
version of gsub works fine but I need more flexibility.

Maybe a sample invokation of the script would help explain what I want.  
Here’s a sample:

INPUT\_STRING = ‘This is getting to be a bear!’  
script invokation -\> snr.rb -regex’(\W)+(\w\w)(\W)+’  
-replacement’$1-\>$2\<-$3’

Should display -\> ‘This -\>is\<- getting -\>to\<- -\>be\<- a bear!’

I’m finding it hard to explain exactly what it is I am looking for -  
simple concept but difficult for me to explain.

Again, thank you for your help.

Hector

---

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 9:39am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/5 "2006-03-03T09:39:27Z")

</div>

Hector wrote:

> # Note: All variables above are set by the user of the program, so I
> 
> return\_value  
> }
> 
> I want return\_value to be -\> ‘This -\>is\<- a test -\>of\<- the emergency’
> 
> Note: I know that I can get it to work with the non-block version of  
> gsub! but I need to use the block version.

In your case you don’t even need groups, because you can nicely anchor  
the  
expression on word boundaries:

> > upcase=true  
> > =\> true
> 
> > ‘This is a test of the emergency’.gsub(/\b\w\w\b/) {|m| “-\>” \<\< (upcase  
> > ? m.upcase : m) \<\< “\<-”}  
> > =\> “This -\>IS\<- a test -\>OF\<- the emergency”

Otherwise

> > ‘This is a test of the emergency’.gsub(/(\W)+(\w\w)(\W)+/) {|m|  
> > “#$1-\>#{upcase ? $2.upcase : $2}\<-#$3”}  
> > =\> “This -\>IS\<- a test -\>OF\<- the emergency”

Note: #$1 in a double quoted string is a shortcut for #{$1}.

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![hector](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/43a26b/32.png) [@hector](https://www.ruby-forum.com/u/hector)\
**Post date:** [March 3, 2006, 2:39am UTC](https://www.ruby-forum.com/t/gsub-wrapper/76007/6 "2006-03-03T02:39:52Z")

</div>

$1 is a global variable which is set to the value matched by the  
bracketed bits. You just treat it like any string.

e.g. “The first parameter was #$1” or number = $2.to\_f

In gsub substitutions the letters ‘\N’ in the substitution text, where  
N is a number from 1 to 9, will be replaced by the substituted  
sequence. If you use double quotes, you will need two backslashes  
because this is not a normal escape sequence.

str = “We love Ruby”  
puts str.gsub(/We (\w+) \w+/, ‘Why do we \1 it?’)  
puts str.gsub(/(\w+)$/, “it because \1 allows us to do cool stuff!”)
