Josh M.
Josh M.

Reputation: 27773

Ruby regexp from variable

Using Ruby 1.8.7 I want to store some regular expressions in the database and have them be easily reconstituted as a Regexp object when I need to use them for validation. I've found that Ruby exhibits some unwanted behavior. For instance:

r = Regexp.new(/^\w+$/i)        => /^\w+$/i
r_i = r.inspect                 => "/^\\w+$/i"
r_s = r.to_s                    => "(?i-mx:^\\w+$)"
r_from_r_i = Regexp.new(r_i)    => /\/^\w+$\/i/
r_from_r_s = Regexp.new(r_s)    => /(?i-mx:^\w+$)/
r == r_from_r_i                 => false
r == r_from_r_s                 => false

What I'd like is to be able to store the Regexp in the database in the form /pattern/options instead of the (?options:pattern) format, because I'm more familiar with the former. But, when creating a new Regexp from a variable, the pattern gets all wacky. Ruby is escaping the /s - so the pattern is invalid.

Is there any way to make Ruby honor the /pattern/options format when parsing a regular expression?

Upvotes: 3

Views: 710

Answers (1)

Arup Rakshit
Arup Rakshit

Reputation: 118261

You can do as below:

r = Regexp.new(/^\w+$/i) # => /^\w+$/i
source,option = r.source,r.options # => ["^\\w+$", 1]
regex = Regexp.new(source,option)
regex == r # => true

options

Returns the set of bits corresponding to the options used when creating this Regexp

source

Returns the original string of the pattern

Now, if you want a single variable to hold all your Regex details, then consider as below:

r = Regexp.new(/^\w+$/i) # => /^\w+$/i
source_option = r.source,r.options # => ["^\\w+$", 1]
regex = Regexp.new(*source_option)
regex == r # => true

Why did yours get false with to_s or inspect?

Read the doc carefully; you can see that Regexp.to_s is saying:

Returns a string containing the regular expression and its options (using the (?opts:source) notation. This string can be fed back in to Regexp::new to a regular expression with the same semantics as the original. (However, Regexp#== may not return true when comparing the two, as the source of the regular expression itself may differ, as the example shows). Regexp#inspect produces a generally more readable version of rxp.

Now, see:

r = Regexp.new(/^\w+$/i) # => /^\w+$/i
r_s = r.to_s
r_from_r_s = Regexp.new(r_s)
r == r_from_r_s # => false
# because the source strings are not same for r and r_from_r_s
r.source # => "^\\w+$"
r_from_r_s.source # => "(?i-mx:^\\w+$)"

The same explanation as above holds for the result of r == r_from_r_i.

Upvotes: 8

Related Questions