Andrew
Andrew

Reputation: 747

Variable expansion in exec from the ruby standard library

What's the correct quoting syntax to allow for variable expansion in the following script?

ARGF.each do |l|
  exec cp #{l} #{l}.bk
end

Thanks

Upvotes: -1

Views: 141

Answers (2)

Andrew
Andrew

Reputation: 747

Use quotes with string interpolation. the problem is that when you run what is verbatim in the ruby docs, ARGF.each do |line|, it does just as says: it loops over lines of the file in the context, but the objective of this script is to copy the filenames-- not access the contents of the files. Therefore when I reference #{l} I am not referencing the filename, but a line within the file.

If you just use ARGF as it is then (i think) it will try to actually read the contents of those files. To reference the names of the files for doing operations like the one above (copy) there are two ways:

ARGF.argv returns an array of the filenames. ARGF.filename returns the filename inside the context of a loop.

Since I'm doing a looping structure I can access the current filename of the loop context with ARGF.filename method.

The correct code looks like this:

ARGF.each do |l|
  exec ("cp #{ARGF.filename} #{ARGF.filename}.bk"
end

Upvotes: -1

Jörg W Mittag
Jörg W Mittag

Reputation: 369468

In Ruby, in order to evaluate a variable, you simply reference it by name. So, for example, to evaluate a local variable named foo, you simply write

foo

Ruby doesn't have a concept of "variable expansion" like a POSIX shell does. In a POSIX shell, everything is a string, and so you expand variables into strings. Ruby has a much richer and much stronger (dynamic) type system, and a much richer syntax.

So, in order to evaluate the local variable (or more precisely, the block argument binding) l, you would simply write

l

Therefore, your code would look something like this:

ARGF.each do |l|
  exec cp l l.bk
end

Which is parsed like this:

ARGF.each do |l|
  exec(cp(l(l.bk())))
end

Note: in this case, the two references to l actually reference two different things: the first l is a message send, the second l is a local variable reference.

Upvotes: 0

Related Questions