[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Clean way to dynamically expand string with "#{expression}"?

Neville Burnell

4/22/2005 6:47:00 AM

How about:

irb(main):001:0> n = 1
=> 1
irb(main):002:0> s = 'n = #{n}'
=> "n = \#{n}"
irb(main):003:0> puts eval('"' + s + '"')
n = 1
=> nil

-----Original Message-----
From: Taisuke Yamada [mailto:tyamadajp@list.rakugaki.org]
Sent: Friday, 22 April 2005 4:35 PM
To: ruby-talk ML
Subject: Clean way to dynamically expand string with "#{expression}"?

Hi.

I'm trying to find a clean way to expand string with "#{...}".
What I want to do is essentially as follows:

data = 123
expr = 'data = #{data}'

puts dosomething(expr)

and get 'data = 123' as a result. Actual content of 'expr' can be
anything, as long as it is a String object.

I came up with following:

puts eval(%Q{"#{expr.gsub('"', '\"')}"})

But this is ugly, and I'm wondering if there's some other, cleaner way
to do the same thing.

Can anyone enlighten me?

Best Regards,
--
Taisuke Yamada




2 Answers

Paul Battley

4/22/2005 9:25:00 AM

0

On 22/04/05, Neville Burnell <Neville.Burnell@bmsoft.com.au> wrote:
> How about:
>
> irb(main):001:0> n = 1
> => 1
> irb(main):002:0> s = 'n = #{n}'
> => "n = \#{n}"
> irb(main):003:0> puts eval('"' + s + '"')
> n = 1
> => nil

If you use eval, you should be careful to escape both backslashes and
quotes in the string. You can also define a method to handle it:

def interpolate(str, bnd)
return eval('"' << str.gsub(/\\/, "\\\\\\\\").gsub(/"/, "\\\\\"")
<< '"', bnd)
end

n = 3
interpolate('n = #{n}', binding) # => "n = 3"
interpolate('\n = #{n}', binding) # => "\\n = 3"
interpolate('\"; `ls`; "n = #{n}', binding) # => "\\\"; `ls`; \"n = 3"

# OK so far...

interpolate('n = #{`ls`}', binding) # => "n = [long directory listing]"

As you can see, there are risks inherent in using eval. This can be
mitigated against by using $SAFE and tainting, and thereby avoiding
eval'ing untrusted input.

Paul.



Denis Mertz

4/22/2005 10:38:00 AM

0

And in a more OO way, you can use

irb(main):001:0> class String
irb(main):002:1> def interpolate(caller)
irb(main):003:2> caller.instance_eval('"' + self + '"')
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> @toto = "afdgfd"
=> "afdgfd"
irb(main):007:0> '123 #{@toto}'.interpolate(self)
=> "123 afdgfd"

ciao

Denis

Neville Burnell wrote:

> How about:
>
> irb(main):001:0> n = 1
> => 1
> irb(main):002:0> s = 'n = #{n}'
> => "n = \#{n}"
> irb(main):003:0> puts eval('"' + s + '"')
> n = 1
> => nil
>
> -----Original Message-----
> From: Taisuke Yamada [mailto:tyamadajp@list.rakugaki.org]
> Sent: Friday, 22 April 2005 4:35 PM
> To: ruby-talk ML
> Subject: Clean way to dynamically expand string with "#{expression}"?
>
> Hi.
>
> I'm trying to find a clean way to expand string with "#{...}".
> What I want to do is essentially as follows:
>
> data = 123
> expr = 'data = #{data}'
>
> puts dosomething(expr)
>
> and get 'data = 123' as a result. Actual content of 'expr' can be
> anything, as long as it is a String object.
>
> I came up with following:
>
> puts eval(%Q{"#{expr.gsub('"', '\"')}"})
>
> But this is ugly, and I'm wondering if there's some other, cleaner way
> to do the same thing.
>
> Can anyone enlighten me?
>
> Best Regards,
> --
> Taisuke Yamada