0

I'm quite new to Ruby so I hope this question isn't already answered elsewhere. But I've been searching here and on the internet for quite a while with no results yet.

I am reading in a bunch of file paths from a text file. Each file path has some expressions (i.e. #{...} ) embedded into the string. For instance:

input = 'E:/files/storage/#{high_or_low}/#{left_or_right}/*.dll'

Anyways, I want to evaluate those strings as if they were ruby code and get those expressions replaced. For instance:

def high_or_low
    'low'
end

def left_or_right
    'left'
end

# It represents a file path on the disk drive
input = 'E:/files/storage/#{high_or_low}/#{left_or_right}/*.dll'
puts input

# Now how do I execute this 'input' string so that it behaves as if it was defined with quotes?
result = eval input
puts result

I purposefully put single quotes around the original input string to show that when the string comes in off the disk, the expression embedded in the string is unevaluated. So how do I evaluate the string with these expressions? Using eval as shown above doesn't seem to work. I get this error:

test_eval.rb:15: compile error (SyntaxError)
test_eval.rb:15: syntax error, unexpected tIDENTIFIER, expecting $end

Thanks

4
  • 1
    The SyntaxError is not related to method calls in the string interpolation. Reduce the test case and show the result in a more useful manner (e.g. just puts). Try to run this "statement" in IRB: E:/files/storage/low/high/*.dll and compare the results. Anyway, once that red herring is eliminated .. then it can be clearly seen when string interpolation occurs, which is at the point of evaluating the literal. If you do want to use the icky eval hack, compare again with the line I suggested running in IRB. Commented Nov 13, 2012 at 17:30
  • Ok, I entered that expression in irb and I saw the syntax error. It appears that the string is getting executed as if it's NOT a string. I still don't know how to fix this... Commented Nov 13, 2012 at 17:45
  • Is there an alternative to eval? Commented Nov 13, 2012 at 17:46
  • Ah, found it... eval '"' + input + '"' Commented Nov 13, 2012 at 18:01

2 Answers 2

1

pst pointed you to why it's failing. As an alternative, which may or may not work depending on what your data looks like... but if it's simple strings with method names (and in particular doesn't contain nested "}"'s...

result = input.gsub(/\#{(.*?)}/) {|s| send($1)}
puts result
Sign up to request clarification or add additional context in comments.

2 Comments

I tried this and magically and mysteriously it worked, but I did get this warning: test_eval.rb:16: warning: regexp has invalid interval test_eval.rb:16: warning: regexp has `}' without escape
Ah, you might need to esacpe the {}'s in that regexp like I did for the #. I didn't get that warning, but perhaps it's due to different Ruby versions. It works by passing the match to a block (s would be "#{string}". $1 is set to the capture in the regexp. We then call send to call that method in the current scope.
0

Ah found it. pst got me started in the correct direction. So once I wrapped the input variable in quotes like this, it worked:

result = eval '"' + input + '"'
puts result

=> E:/files/storage/low/left/*.dll

1 Comment

no idea why someone downvoted this? This works perfectly and is quite a simple answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.