137

I need to convert string like "/[\w\s]+/" to regular expression.

"/[\w\s]+/" => /[\w\s]+/

I tried using different Regexp methods like:

Regexp.new("/[\w\s]+/") => /\/[w ]+\//, similarly Regexp.compile and Regexp.escape. But none of them returns as I expected.

Further more I tried removing backslashes:

Regexp.new("[\w\s]+") => /[w ]+/ But not have a luck.

Then I tried to do it simple:

str = "[\w\s]+"
=> "[w ]+"

It escapes. Now how could string remains as it is and convert to a regexp object?

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
cmthakur
  • 2,266
  • 4
  • 18
  • 23

6 Answers6

177

Looks like here you need the initial string to be in single quotes (refer this page)

>> str = '[\w\s]+'
 => "[\\w\\s]+" 
>> Regexp.new str
 => /[\w\s]+/ 
alony
  • 10,725
  • 3
  • 39
  • 46
151

To be clear

  /#{Regexp.quote(your_string_variable)}/

is working too

edit: wrapped your_string_variable in Regexp.quote, for correctness.

deprecated
  • 5,142
  • 3
  • 41
  • 62
Sergey Gerasimov
  • 2,035
  • 2
  • 14
  • 12
38

This method will safely escape all characters with special meaning:

/#{Regexp.quote(your_string)}/

For example, . will be escaped, since it's otherwise interpreted as 'any character'.

Remember to use a single-quoted string unless you want regular string interpolation to kick in, where backslash has a special meaning.

sandstrom
  • 14,554
  • 7
  • 65
  • 62
  • 2
    Nice because it explains how we can protect the string variable that may contain signs (such as `+.`) that would be interpreted in the Regexp. – Romain Champourlier May 23 '14 at 16:39
  • 1
    This doesn't do what OP is asking on Ruby 2.1, it converts "[\w\s]+" => /\[w\ \]\+/ – Luca Spiller Nov 05 '15 at 12:15
  • @LucaSpiller you need to use a single-quoted string, backslash is treated as a special character in double-quoted strings, which is why e.g. `"\n"` is a newline but `'\n'` isn't. – sandstrom Dec 27 '15 at 15:47
10

Using % notation:

%r{\w+}m => /\w+/m

or

regex_string = '\W+'
%r[#{regex_string}]

From help:

%r[ ] Interpolated Regexp (flags can appear after the closing delimiter)

BitOfUniverse
  • 5,903
  • 1
  • 34
  • 38
7

The gem to_regexp can do the work.

"/[\w\s]+/".to_regexp => /[\w\s]+/

You also can use the modifier:

'/foo/i'.to_regexp => /foo/i

Finally, you can be more lazy using :detect

'foo'.to_regexp(detect: true)     #=> /foo/
'foo\b'.to_regexp(detect: true)   #=> %r{foo\\b}
'/foo\b/'.to_regexp(detect: true) #=> %r{foo\b}
'foo\b/'.to_regexp(detect: true)  #=> %r{foo\\b/}
ryan
  • 847
  • 1
  • 10
  • 18
0

I just ran into this, where I literally need to change the string '/[\w\s]+/' to a regex in a transpiler. I used eval:

irb(main):001:0> eval( '/[\w\s]+/' )
=> /[\w\s]+/
Joseph
  • 1,354
  • 12
  • 15