[regexp] How to convert string "/regexp/i" to /regexp/i -?

When i try to use:

Regexp.new("/regexp/i")

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?

···

--
Posted via http://www.ruby-forum.com/\.

When i try to use:

Regexp.new("/regexp/i")

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?

Try without the quotes

Regexp.new(/regexp/i)

=> /regexp/i

Cheers,

···

2009/8/21 Joao Silva <rubyforum@thisisnotmyrealemail.com>:

--
JJ Fleck
PCSI1 Lycée Kleber

Joao Silva wrote:

When i try to use:

Regexp.new("/regexp/i")
      

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?
  
If that is exactly the kind of string you are expecting, I think you are stuck with having to use eval.

irb(main):001:0> r = eval("/regexp/i")
=> /regexp/i
irb(main):002:0> r.match("REGEXP")
=> #<MatchData "REGEXP">

If you do not need the options, you could just grab the inner part and make a regexp out of that:

irb(main):001:0> re = "/som.r.g.x\d+/i"
=> "/som.r.g.xd+/i"
irb(main):002:0> re = "/som.r.g.x\\d+/i".match(/\/(.*)\/[^\/]/)[1]
=> "som.r.g.x\\d+"
irb(main):003:0> /#{re}/.match("someregex1123")
=> #<MatchData "someregex1123">

Not really a great solution, though, as you lose information.

-Justin

Regexp.new(/regexp/i)

Joao Silva wrote:

···

When i try to use:

Regexp.new("/regexp/i")
      

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?

Joao Silva wrote:

When i try to use:

Regexp.new("/regexp/i")

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?

str = "/regexp/i"
pieces = str.split("/")
pattern = pieces[1]

my_regex = Regexp.new(pattern, true)

md = my_regex.match("hello ReGexP")
puts md[0]

--output:--
ReGexP

Or, more generally:

str = "/reg.*?exp/im"
pieces = str.split("/")
pattern = pieces[1]
flags = pieces[2]

arg_two = 0

flags.length.times do |i|
  case flags[i, 1]
  when "i"
    arg_two |= Regexp::IGNORECASE
  when "m"
    arg_two |= Regexp::MULTILINE
  when "x"
    arg_two |= Regexp::EXTENDED
  end

end

regex = Regexp.new(pattern, arg_two)

test_str =<<ENDOFSTRING
hello rEG
world exP
ENDOFSTRING

md = regex.match(test_str)
if md
  puts md[0]
end

--output:--
rEG
world exP

···

--
Posted via http://www.ruby-forum.com/\.

class String
  def to_r
    Regexp.new(*strip.match(/\/(.*)\/(.*)/)[1,2])
  end
end

"/regexp/i".to_r # => /regexp/i

···

On Fri, Aug 21, 2009 at 4:18 AM, Joao Silva < rubyforum@thisisnotmyrealemail.com> wrote:

When i try to use:

>> Regexp.new("/regexp/i")
=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?
--
Posted via http://www.ruby-forum.com/\.

In the spirit of http://xkcd.com/979/ here's a better answer:
http://rubygems.org/gems/to_regexp
This gem solves the problem. Source:
http://stackoverflow.com/questions/6669425/convert-a-regular-expression-in-a-string-to-a-regexp-object-in-ruby/6669653#6669653

Once this gem is installed, you can call String#to_regexp and all is
well.

···

--
Posted via http://www.ruby-forum.com/.

Something like:
   
   key = "ixm"

   x = str.reverse_index('/')

   v = str[x+1..-1]

   o = v.characters.inject(0){ |s,c| b = key.index(c); b ? 2**b : 0 }

   Regexp.new(str[1...x], o)

Or

  eval "%r#{str}"

If safety is a concern you can get Pretty Good(tm) safety by wrapping it in
a threaded $SAFE=4. Too bad Ruby doesn't support %R, then it would
perfectly safe.

Fleck Jean-Julien wrote:

···

2009/8/21 Joao Silva <rubyforum@thisisnotmyrealemail.com>:

How i can convert this proper way?

Try without the quotes

Regexp.new(/regexp/i)

=> /regexp/i

Cheers,

I cannot do this without quotes - i need get it from string. Only thing
i have is "/regexp/i" string.

Thanks!
--
Posted via http://www.ruby-forum.com/\.

Justin Collins wrote:

Joao Silva wrote:

When i try to use:

Regexp.new("/regexp/i")
      

=> /\/regexp\/i/

But it's not what i want - i need:

/regexp/i

:frowning:

How i can convert this proper way?
  
If that is exactly the kind of string you are expecting, I think you are stuck with having to use eval.

irb(main):001:0> r = eval("/regexp/i")
=> /regexp/i
irb(main):002:0> r.match("REGEXP")
=> #<MatchData "REGEXP">

If you do not need the options, you could just grab the inner part and make a regexp out of that:

irb(main):001:0> re = "/som.r.g.x\d+/i"
=> "/som.r.g.xd+/i"
irb(main):002:0> re = "/som.r.g.x\\d+/i".match(/\/(.*)\/[^\/]/)[1]
=> "som.r.g.x\\d+"
irb(main):003:0> /#{re}/.match("someregex1123")
=> #<MatchData "someregex1123">

Not really a great solution, though, as you lose information.

-Justin

I should add, for the second approach you could also parse the options and then manually build up the regexp with the corresponding options. That is the "non-lazy" way, though :slight_smile:

-Justin

Michal Zacik wrote:

Regexp.new(/regexp/i)

? Without ""?

···

--
Posted via http://www.ruby-forum.com/\.

Josh Cheek wrote:

class String
  def to_r
    Regexp.new(*strip.match(/\/(.*)\/(.*)/)[1,2])
  end
end

"/regexp/i".to_r # => /regexp/i

Doesn't work in this case:

str = "/reg.*?exp/m"

test_str =<<ENDOFSTRING
hello rEG
world exP
ENDOFSTRING

...nor when there is more than one flag.

···

--
Posted via http://www.ruby-forum.com/\.

Joao Silva <rubyforum@thisisnotmyrealemail.com> writes:

Fleck Jean-Julien wrote:

How i can convert this proper way?

Try without the quotes

Regexp.new(/regexp/i)

=> /regexp/i

Cheers,

I cannot do this without quotes - i need get it from string. Only thing
i have is "/regexp/i" string.

string="/regexp/i"
Regexp.new(eval(string))

···

2009/8/21 Joao Silva <rubyforum@thisisnotmyrealemail.com>:

--
__Pascal Bourguignon__

Sorry, it gave me what I expected, and Ruby is usually intuitive, so I
thought I got it right. This class, however, is not. I had to learn some of
it's internal logic to figure it out. (they define constants for each flag,
these constants are integers, you then have to add the values of the
constants of all the flags together to get the new options value)

class String
    return nil unless self.strip.match(/\A\/(.*)\/(.*)\Z/mx)
    regexp , flags = $1 , $2
    return nil if !regexp || flags =~ /[^xim]/m

    x = /x/.match(flags) && Regexp::EXTENDED
    i = /i/.match(flags) && Regexp::IGNORECASE
    m = /m/.match(flags) && Regexp::MULTILINE

    Regexp.new regexp , [x,i,m].inject(0){|a,f| f ? a+f : a }
  end
end

#fail cases
"regexp".to_r # => nil
"regexp/i".to_r # => nil
"/regexp/mk".to_r # => nil
<<-ENDOFSTRING.to_r # => nil
hello rEG
world exP
ENDOFSTRING
"/regexp/mk
hello rEG
world exP".to_r # => nil

#pass cases
"/reg/".to_r # => /reg/
" /reg/x ".to_r # => /reg/x
"/reg.*?exp/m".to_r # => /reg.*?exp/m
"/regexp/x".to_r # => /regexp/x
"/abc
def
ghi/xi".to_r # => /abc
                      # def
                      # ghi/ix

"//".to_r # => //
"/abc/i".to_r # => /abc/i
"/abc/x".to_r # => /abc/x
"/abc/m".to_r # => /abc/m
"/abc/ix".to_r # => /abc/ix
"/abc/im".to_r # => /abc/mi
"/abc/xm".to_r # => /abc/mx
"/abc/ixm".to_r # => /abc/mix
"/abc/mxi".to_r # => /abc/mix

···

On Fri, Aug 21, 2009 at 5:27 AM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

Josh Cheek wrote:
> class String
> def to_r
> Regexp.new(*strip.match(/\/(.*)\/(.*)/)[1,2])
> end
> end
>
> "/regexp/i".to_r # => /regexp/i
>

Doesn't work in this case:

str = "/reg.*?exp/m"

test_str =<<ENDOFSTRING
hello rEG
world exP
ENDOFSTRING

...nor when there is more than one flag.

--
Posted via http://www.ruby-forum.com/\.

Pascal J. Bourguignon wrote:

Joao Silva <rubyforum@thisisnotmyrealemail.com> writes:

Cheers,

I cannot do this without quotes - i need get it from string. Only thing
i have is "/regexp/i" string.

string="/regexp/i"
Regexp.new(eval(string))

I tried this, but it's totally unsafe way (these strings are provided by
user).

···

--
Posted via http://www.ruby-forum.com/\.

Eval is a mighty tool for a tiny task

option = str[-1] # Ruby 1.9, use [-1,1] in 1.8

Regexp::new( str[1..-3], option )

HTH
R

···

On Fri, Aug 21, 2009 at 12:00 PM, Pascal J. Bourguignon<pjb@informatimago.com> wrote:

Joao Silva <rubyforum@thisisnotmyrealemail.com> writes:

Fleck Jean-Julien wrote:

2009/8/21 Joao Silva <rubyforum@thisisnotmyrealemail.com>:

How i can convert this proper way?

Try without the quotes

Regexp.new(/regexp/i)

=> /regexp/i

Cheers,

I cannot do this without quotes - i need get it from string. Only thing
i have is "/regexp/i" string.

string="/regexp/i"
Regexp.new(eval(string))

--
__Pascal Bourguignon__

--
module Kernel
  alias_method :λ, :lambda
end

"Regexp.new" is superfluous:

irb(main):002:0> eval("/regexp/i").class
=> Regexp
irb(main):003:0>

Cheers

robert

···

2009/8/21 Pascal J. Bourguignon <pjb@informatimago.com>:

Joao Silva <rubyforum@thisisnotmyrealemail.com> writes:

Fleck Jean-Julien wrote:

2009/8/21 Joao Silva <rubyforum@thisisnotmyrealemail.com>:

How i can convert this proper way?

Try without the quotes

Regexp.new(/regexp/i)

=> /regexp/i

Cheers,

I cannot do this without quotes - i need get it from string. Only thing
i have is "/regexp/i" string.

string="/regexp/i"
Regexp.new(eval(string))

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Josh Cheek wrote:

Sorry, it gave me what I expected, and Ruby is usually intuitive, so I
thought I got it right.

Mine solution has problems too--for the same reason. It needs something
like this:

arg_two = nil if arg_two == 0
regex = Regexp.new(pattern, arg_two)

···

--
Posted via http://www.ruby-forum.com/\.

If the strings are provided by an untrusted source, don't use any solution that uses eval().

Instead, use a solution that recognizes the string contains a regexp and then uses a regexp constructor after pulling the relevant data out of the string. Something along the lines of:

def parse_input(str)
   if md = %r{^/(.*)+/(.*)*$}.match(str)
     #it's a regexp
     pattern = md[1]
     if md[2]
       # deal with the flags
       flags = deal_with(md[2]
     end
     Regexp.new(pattern, flags)
   else
     ...
   end
end

Ben

···

On Aug 21, 2009, at 06:04, Joao Silva wrote:

I tried this, but it's totally unsafe way (these strings are provided by
user).

Ben Giddings wrote in post #844686:

If the strings are provided by an untrusted source, don't use any
solution that uses eval().

Yes.

Instead, use a solution that recognizes the string contains a regexp
and then uses a regexp constructor after pulling the relevant data out
of the string. Something along the lines of:

def parse_input(str)
   if md = %r{^/(.*)+/(.*)*$}.match(str)

Nice try, but that regexp isn't safe. I think Ruby's design decision
here was a bad one. In Ruby, you need \A to match only at the start of
string, and \z to match only at the end of string (whereas you might
expect ^ and $ to mean that)

Also, I'd suggest that repeated capture groups are a bit confusing, e.g.
where you write (.*)+ when (.*) by itself would be fine. Because * is
greedy, .* will capture as much as possible so the + will only repeat
once.

Anyway, here's a trick for handling the flags: note that /foo/i can be
represented as (?i:foo)

    raise "Invalid regexp" unless %r{\A/(.*)/([mix]*)\z} =~ str
    Regexp.new("(?#{$2}:#{$1})")

···

--
Posted via http://www.ruby-forum.com/\.