Is it possible to create a dynamic regular expression in Ruby
You can use #{}
just like in a string.
1.9.2p290 :001 > some_string = "033112"
=> "033112"
1.9.2p290 :002 > a_regex = /[A-Z]{1,4}#{some_string}[A-Z]{1-5}-EQB.html/
=> /[A-Z]{1,4}033112[A-Z]{1-5}-EQB.html/
Ruby how to construct dynamic regexp?
You can use interpolation in the same way as with strings:
/(<\s*?div\s*?id="#{my_id}"\s*?>.*?<\/div>)/im
Regular expression in Ruby dynamic creation
You want to use Regexp.union
:
union(pat1, pat2, ...) → new_regexp
union(pats_ary) → new_regexpReturn a
Regexp
object that is the union of the given patterns, i.e., will match any of its parts. The patterns can beRegexp
objects, in which case their options will be preserved, orString
s.
So just this:
regex = Regexp.union(phrases)
For example:
>> phrases = %w[pancakes egg$]
=> ["pancakes", "egg$"]
>> puts Regexp.new(phrases.join('|')).inspect
/pancakes|egg$/
>> puts Regexp.union(phrases).inspect
/pancakes|egg\$/
Note the escaped $
in the union
version. There's also Regexp.quote
(AKA Regexp.escape
) if you need to selectively escape particular strings. Generally you don't want to just mash a bunch of random strings together to build a regex, the regex syntax characters will get you every time; use Regex.union
for a big alternation or send your pieces through Regex.escape
before putting them together.
You could also do a LIKE query if you wanted to keep it inside the database:
Foo.where('phrase like ?', "%#{params[:some_text]}%")
or skip all the pattern matching stuff and its escaping problems altogether and do a simple string position check:
Foo.where('position(? in phrase) != 0', params[:some_text])
Both of these will do table scans but so will your Foo.all
.
ror, how to make a regex dynamic?
In ruby you can create the regexp from a string representation using Regexp.new
:
if (params[:to].to_s =~ Regexp.new("^r\\+.*@#{Regexp.quote(SITE_CONFIG['mail_host'])}$")) == nil
Variable containing regex as string/generating regex dynamically and trouble with \b
This isn't hard, but it appears you're making it that way:
foo = '\b[ab]'
Regexp.new(foo) # => /\b[ab]/
/#{foo}/ # => /\b[ab]/
or:
foo = "\\b[ab]"
Regexp.new(foo) # => /\b[ab]/
/#{foo}/ # => /\b[ab]/
Ruby is perfectly happy to use a string to create a pattern, you just have to do it right.
Strings are great building blocks for patterns because we can build patterns up from smaller pieces, then finally join the pieces we want into a large pattern. We do that in all sorts of languages too, not just Ruby.
WORD_BOUNDARY = '\b'
WORD_CHARACTERS = '[a-zA-Z]'
WORD_PATTERN = /#{WORD_BOUNDARY}#{WORD_CHARACTERS}+#{WORD_BOUNDARY}/
WORD_PATTERN # => /\b[a-zA-Z]+\b/
/#{WORD_PATTERN}/ # => /(?-mix:\b[a-zA-Z]+\b)/
Regexp.new(WORD_PATTERN) # => /\b[a-zA-Z]+\b/
It's also important to note the difference between "\b"
and '\b'
. If the string allows interpolation of variables and escaped values, then \b
will be treated as a backspace. That's NOT what you want:
"\b" # => "\b"
"\b".ord # => 8
Instead, use a non-interpreted string:
'\b' # => "\\b"
Or double-escape the word-boundary characters.
You can easily dynamically generate a pattern, you just have to follow the rules for string interpolation and understand that escaped characters have to be double-escaped if the string is interpolated.
Need a regular expression to match a dynamically-determined repeat count
That is not possible in regex since it is not a regular language (that's easy to prove with the Pumping Lemma for Regular Languages). I'm not sure how much more powerful ruby regex is than a true Regular Expression, but I doubt it's powerful enough for this. You can set a finite limit on it and state each possibility like:
a1|aa2|aaa3|aaaa4|aaaaa5||aaaaaa6||aaaaaaa7||How to Create a Dynamic Regular Expression in Ruby8||How to Create a Dynamic Regular Expression in Rubya9
Since all finite lanugages are regular, but it would be much easy to use string operations to count the number of times a letter appears and then parse for that integer in the string right after the last of that letter.
Apply regex to a dynamic Rails link
When you call a _path
or _url
method, all it does is return a string, so you can gsub
that result as you need to.
Note that Rails will treat that as going to /leisure/venuename
in any link/form/or redirect due to the #
being a location on a particular page, not a unique URL.
Edit
Managed to get a stricter regex working. Problem with .*
is it gets slashes and such too.
path.gsub(/\/[a-zA-Z0-9\-\_]*$/) do |match|
"##{match}"
end
ruby include, dynamic letters and symbols
One way to do this is through Regular Expressions ('regex' for short). Two good sources of information is Regular Expression.info and Rubular which is more Ruby centric.
One way to use regex on a string is the String#match
method:
names[2].match(/Q\d\dP\d\d/) # /d stands for digit
This will return the string if there is a match and it will return nil
if there isn't.
"Q42P67".match(/Q\d\dP\d\d/) #=> "Q42P67"
"H33P55".match(/Q\d\dP\d\d/) #=> nil
This is helpful in an if
condition since a returned string is 'truthy' and nil
is 'falsely'.
names[2] = "Q42P67"
if names[2].match(/Q\d\dP\d\d/)
# Will execute code here
end
names[2] = "H33P55"
if names[2].match(/Q\d\dP\d\d/)
# Will not execute code here
end
I hope that helps until you dig further into your study of Regular Expressions.
EDIT:
Note that the Q and P in /Q\d\dP\d\d/
are capital letters. If case is not important, you can append an 'i' for case-insensitivity. /Q\d\dP\d\d/i
will capture "Q42P67" and "q42P67"
Ruby regular expression using variable name
The code you think doesn't work, does:
var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' ) # => "a test foo"
Things get more interesting if var can contain regular expression meta-characters. If it does and you want those matacharacters to do what they usually do in a regular expression, then the same gsub will work:
var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"
However, if your search string contains metacharacters and you do not want them interpreted as metacharacters, then use Regexp.escape like this:
var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"
Or just give gsub a string instead of a regular expression. In MRI >= 1.8.7, gsub will treat a string replacement argument as a plain string, not a regular expression:
var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"
(It used to be that a string replacement argument to gsub was automatically converted to a regular expression. I know it was that way in 1.6. I don't recall which version introduced the change).
As noted in other answers, you can use Regexp.new as an alternative to interpolation:
var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"
Related Topics
Good Resources to Learn MACruby
Installing Pl/Ruby for Postgresql 8.3
Ruby on Rails - Rack-Cors Multiple Origins with Different Resources
Using Rvm, But Can't Set Current Ruby Version (Ubuntu 11.10)
Using Rest-Client to Download a File to Disk Without Loading It All in Memory First
How to Read an Ini File in Ruby
How Does One Downgrade Jekyll to Work with Github Pages
How to Extend a Class from an Initializer and Have It Reload in Development Environment
I Can't Remove Whitespaces from a String Parsed by Nokogiri
Rvm with Jruby 1.7.0 "Unknown Ruby Interpreter"
How to Run Multiple Lines of Ruby in HTML.Erb File
What's the Efficient Way to Multiply Two Arrays and Get Sum of Multiplied Values in Ruby
Using Ruby CSV to Extract One Column