Nick M
Nick M

Reputation: 2532

Evaluating Ruby regular expressions stored in database

I am building a tool to keep rewrite rules for all sorts of content into a database table:

+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| replace_text | varchar(100) | NO   |     | NULL    |                |
| replace_with | varchar(100) | YES  |     | NULL    |                |
| scp          | varchar(20)  | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+

When I process content I just pull all relevant rules (based on the scp field) and run a <variable>.gsub(replace_text, replace_with) to change whatever is required.

My question is whether or not it's possible to check if replace_text contains a valid regexp and use that instead of replacing the plain text contents of the column?

Because basically:

 "Sometimes it's best to keep things simple".gsub('/[aeiou]/',"x")

outputs "Sometimes it's best to keep things simple"

while:

"Sometimes it's best to keep things simple".gsub(eval('/simple/'),"x")

or

"Sometimes it's best to keep things simple".gsub(/simple/,"x")

Output what I need:

"Sometimes it's best to keep things x"

So basically what I'm looking for is a way to find out if a string contains a valid regular expression or not.

I've searched around and it seems regular expressions cannot be validated with other regular expressions. Using eval() all the time is not an option because the variable may not always contain a regular expression, but just some plain text to remove/replace.

TIA

Upvotes: 1

Views: 291

Answers (4)

Wayne Conrad
Wayne Conrad

Reputation: 107989

Given a string containing a valid regular expression, Regexp.new returns successfully:

Re1.9.3-p484 :001 > Regexp.new("asdf")
 => /asdf/ 

Given a string containing an invalid regular expression, Regexp.new raises RegexpError:

1.9.3-p484 :002 > Regexp.new("asdf)")
RegexpError: unmatched close parenthesis: /asdf)/

therefore:

def pattern_to_regexp(pattern)
  Regexp.new(pattern)
rescue RegexpError
  nil
end
alias valid_regexp_pattern? pattern_to_regexp

returns a Regexp if possible, or a nil if the pattern string is not a valid regular expression.

Since a Regexp is truthy, and nil is falsy, valid_regexp_pattern is the same method.

To use it:

s.gsub(pattern_to_regexp(pattern) || pattern, replacement)

This works because String#gsub will take either a Regexp or a String as the search argument.

Upvotes: 3

Naren Sisodiya
Naren Sisodiya

Reputation: 7288

addition to Billy's answer you can also use following

record.replace_test.gsub /#{record.replace_with}/, 'x'

Upvotes: 0

Billy Chan
Billy Chan

Reputation: 24815

You can use Regexp class to generate regexp according to the store pattern in text.

record = Record.last
record.replace_test.gsub Regexp.new(record.replace_with), 'x'

Upvotes: 1

shivam
shivam

Reputation: 16506

So basically what I'm looking for is a way to find out if a string contains a valid regular expression or not.

try this:

str = "Sometimes it's best to keep things simple"
if str =~ /simple/
 #do your thing
end

You can try match too:

do_something if str.match('simple')

Upvotes: 1

Related Questions