# Regexp.escape with un-escapes

**URL:** <https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880>\
**Category:** Ruby\
**Created:** [December 6, 2009, 4:19pm UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880 "2009-12-06T16:19:20Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [December 6, 2009, 4:19pm UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880/1 "2009-12-06T16:19:20Z")

</div>

Hi–

I want to translate a string into a regular expression, but I want to  
“un-escape” portions as raw regexp. For example:

“here is a setting ‘a’ equal to ((\d+))”

So I want to Regexp.escape the string, before I pass it to Regexp.new,  
but I want what’s in the (( )) to stay exactly the same with the  
double-parens removed.

I know that has to be a fairly concise way to do this, but all I’ve  
come up with is some very ugly brute force code that iterates back and  
forth using index ‘((’ and index ‘))’.

Any suggestions?

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [December 6, 2009, 4:33pm UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880/2 "2009-12-06T16:33:47Z")

</div>

Thomas S. wrote:

> Hi–
> 
> I want to translate a string into a regular expression, but I want to  
> “un-escape” portions as raw regexp. For example:
> 
> “here is a setting ‘a’ equal to ((\d+))”
> 
> So I want to Regexp.escape the string, before I pass it to Regexp.new,  
> but I want what’s in the (( )) to stay exactly the same with the  
> double-parens removed.
> 
> I know that has to be a fairly concise way to do this, but all I’ve  
> come up with is some very ugly brute force code that iterates back and  
> forth using index ‘((’ and index ‘))’.
> 
> Any suggestions?

Why, yes! Use a regexp to find the (( )) bits, and then extract them,  
don’t escape them, and paste the whole regexp together. It’s a bit  
ironic to me that in a regexp-handling routine, you’re doing brute-force  
index searches. 🙂

Best,  
–Â  
MarnenÂ Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [December 6, 2009, 5:22pm UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880/3 "2009-12-06T17:22:32Z")

</div>

On Dec 6, 10:33 am, Marnen Laibow-Koser [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Why, yes! Use a regexp to find the (( )) bits, and then extract them,  
> don’t escape them, and paste the whole regexp together. It’s a bit  
> ironic to me that in a regexp-handling routine, you’re doing brute-force  
> index searches. 🙂

You are right, it is ironic! Your suggestion helped some. I came up  
with:

```
def __when_string_to_regexp(str)
  rexps = []
  str = str.gsub(/\(\((.*?)\)\)/) do |m|
    rexps << ['(' + $1 + ')']
    "%s"
  end
  str = Regexp.escape(str)
  str = str % rexps
  str = str.gsub(/(\\\ )+/, '\s+')
  Regexp.new(str, Regexp::IGNORECASE)
end

```

It’s still not perfect b/c it means end users won’t be able to use  
“%s” in a string without it messing up --stitching it back together  
seems to be the hard part. But I’ll keep working on it.

Thanks.

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [December 6, 2009, 6:45pm UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880/4 "2009-12-06T18:45:39Z")

</div>

There is a feature in String#split (documented in 1.9, undocumented in  
1.8.6 but still present) whereby if the split RE contains capture  
groups, those capture groups will be included in the resulting array.

> > s = ‘here is (a) setting ‘a’ equal to ((\d+))’  
> > =\> “here is (a) setting ‘a’ equal to ((\d+))”
> 
> > Regexp.new(s.split(/(((._?)))/).map { |x| x =~ /\A(((._)))\z/ ? $1 : Regexp.escape(x) }.join)  
> > =\> /here\ is\ (a)\ setting\ ‘a’\ equal\ to\ (\d+)/

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [December 8, 2009, 6:10am UTC](https://www.ruby-forum.com/t/regexp-escape-with-un-escapes/179880/5 "2009-12-08T06:10:48Z")

</div>

On Dec 6, 12:45 pm, Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> There is a feature in String#split (documented in 1.9, undocumented in  
> 1.8.6 but still present) whereby if the split RE contains capture  
> groups, those capture groups will be included in the resulting array.
> 
> > > s = ‘here is (a) setting 'a' equal to ((\d+))’
> 
> =\> “here is (a) setting ‘a’ equal to ((\d+))”\>\> Regexp.new(s.split(/(((._?)))/).map { |x| x =~ /\A(((._)))\z/ ? $1 : Regexp.escape(x) }.join)
> 
> =\> /here\ is\ (a)\ setting\ ‘a’\ equal\ to\ (\d+)/

Weird, but cool. Does the trick. Thanks.
