Executing the output of a loop

Hi,

I have this simple loop:

(1…12).each do |i|
puts “t#{i}.showURL”
end

Which produces the following output:

t1.showURL
t2.showURL
t3.showURL
t4.showURL
t5.showURL
t6.showURL
t7.showURL
t8.showURL
t9.showURL
t10.showURL
t11.showURL
t12.showURL

My question is this: How can I actually execute the output of the
script? (I want to execute the output, not just have it printed to the
screen)

In bash, I would use backticks `` or dollar-bracket $()

Thanks,

Dwight

you could use eval, passing in the string.

On Thu, Sep 8, 2011 at 9:35 AM, dwight schrute [email protected]
wrote:

t1.showURL
t12.showURL

Dwight


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


Sincerely,

Isaac S.
Section C-4B Vice Chief, Order of the Arrow
Vice Chief of Administration, Tecumseh #65
Eagle Scout

On Thu, Sep 8, 2011 at 3:35 PM, dwight schrute [email protected]
wrote:

t1.showURL
t12.showURL

My question is this: How can I actually execute the output of the
script? (I want to execute the output, not just have it printed to the
screen)

In bash, I would use backticks `` or dollar-bracket $()

backticks also work in Ruby. Also system or %x{}:

(1…12).each do |i|
t#{i}.showURL
end

(1…12).each do |i|
sytem(“t#{i}.showURL”)
end

(1…12).each do |i|
%x{t#{i}.showURL}
end

Jesus.

backticks execute it as though it were in the shell, not as ruby. Using
eval
evaluates it as ruby.

On Thu, Sep 8, 2011 at 9:53 AM, dwight schrute [email protected]
wrote:


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


Sincerely,

Isaac S.
Section C-4B Vice Chief, Order of the Arrow
Vice Chief of Administration, Tecumseh #65
Eagle Scout

Nice. Thank you Issac. That worked perfectly.

I have tried the using backticks / system / %x but get the following
error:

./urls2.rb:41:in ``’: No such file or directory - t1.showURL
(Errno::ENOENT)
from ./urls2.rb:41:in block in <main>' from ./urls2.rb:40:ineach’
from ./urls2.rb:40:in `’

Any further help is much appreciated!

2011/9/8 Jess Gabriel y Galn [email protected]:

t11.showURL
backticks also work in Ruby. Also system or %x{}:
%x{t#{i}.showURL}
end

There’s also exec and if one wants to collect the output there is
IO.popen and Open3.popen…

Initially I had thought (and apparently Isaac did as well) that the
task at hand was to execute Ruby code. However, in that case I would
rather do

ts = […]
ts.each {|t| t.showURL}

Where ts contains all "t"s which have a method “showURL” doing whatever.

Kind regards

robert

This is almost certainly the wrong design, as local variables
aren’t really supposed to be used in this way.

It does not matter how they are “supposed” to be used.

Ruby does not impose it on him.

eval() is a perfectly legit way to solve the problem description he has
given.

There is no “evil user input” at all.

eval() works and can be used without thinking that it is the wrong
choice for the given problem.

El 08/09/2011 17:27, “Robert K.” [email protected]
escribi:

2011/9/8 Jess Gabriel y Galn [email protected]:

On Thu, Sep 8, 2011 at 3:35 PM, dwight schrute [email protected]
wrote:

t1.showURL
t12.showURL

end

There’s also exec and if one wants to collect the output there is
IO.popen and Open3.popen…

Initially I had thought (and apparently Isaac did as well) that the
task at hand was to execute Ruby code.

yes, it seems I misunderstood the question. Sorry for the noise.

Jesus

Isaac S. wrote in post #1020785:

you could use eval, passing in the string.

Beware that eval can execute any ruby code, which in turn can execute
any shell code, e.g. via system(), so is dangerous if the data could
have come from an untrusted source.

Normally I would recommend using send() for something like this:

meth = :showURL # dynamic method name in variable
obj.send(meth) # call that method

However what’s dynamic in your case is that you’re trying to pick one of
12 local variables called “t1” to “t12”.

This is almost certainly the wrong design, as local variables aren’t
really supposed to be used in this way.

I’m guessing that earlier on you had 12 lines of code to assign to those
12 variables? What you probably want is an Array or Hash instead. Then
(a) you can create those 12 instances in better ways (e.g. in a loop);
and
(b) you can do your lookup directly without any eval tricks:

t = []
t[0] = …
t[1] = …

… later …

(0…11).each do |i|
t[i].showURL
end

Then you’ll find there’s an even cleaner way to iterate:

t.each do |elem|
elem.showURL
end

On 09.09.2011 05:32, Marc H. wrote:

There is no “evil user input” at all.

eval() works and can be used without thinking that it is the wrong
choice for the given problem.

It would be better to move from t1, t2, … t12 to an array t[1…12] (or
t[0…11]) and then use each on that. While legit, eval shows a bad
design
underneath that should be fixed instead.

– Matthias

Thank you all for the additional feedback and help. Whilst eval is
working, I will explore these other options as they sound like
potentially better practise.

Dwight.

On Fri, Sep 9, 2011 at 4:32 AM, Marc H. [email protected]
wrote:

It does not matter how they are “supposed” to be used.

Ruby does not impose it on him.

eval() is a perfectly legit way to solve the problem description he has
given.

It will solve the problem, yes, but in not using an array, you lose
the benefits of flexibility. Local variables with numbered suffixes is
just reinventing something you already have as part of the language.
Using eval instead of a basic language construct would be a pretty bad
habit to get into.

On Thu, Sep 8, 2011 at 10:32 PM, Marc H. [email protected]
wrote:

There is no “evil user input” at all.

eval() works and can be used without thinking that it is the wrong
choice for the given problem.

It is the wrong choice, not because of security risks, but because it
means
you are using your binding as a hash, instead of using a hash as a hash
(though in this case, an array is probably the better choice).

For OP, here is an example of what it might look like

fyi, Rubyists usually try to pick more meaningful names

in this case, ts represents the plural of t :slight_smile:

ts = [ …init code… ]

a direct mapping of your original idea

(0…12).each do |i|
t = ts[i]
puts t.showURL # also, convention in Ruby is snake_case not cameCase
end

probably what you really want

ts.each { |t| puts t.showURL }