0

I want to remove string interpolation for eval.

I have a lot of places with such code, so only one option is modifying the condition to unescape code.

I found a regexp that works well

"\#{user.name}"[/[^\#{}]+/]

as result, I have "user.name"

but such code removing curly braces in blocks as well

"\#{[1,2,3].map { |el| el }.join(',')}"[/[^\#{}]+/]

returns

"[1,2,3].map "

the expected result is:

"[1,2,3].map { |el| el }.join(',')"

Any ideas how to solve it?

2
  • Try your_str[/#({(?:[^{}]++|\g<1>)*})/, 1].gsub(/[{}]/, ""), see demo. Commented Nov 20, 2018 at 13:18
  • 2
    If the goal of this is to make eval safe, don't bother. You would basically need to implement a Ruby static analyzer to truly do that. Commented Nov 20, 2018 at 14:26

1 Answer 1

2

You can use gsub and named regex in this case

> reg = Regexp.new('\\#{(?<content>.+)}')
=> /\#{(?<content>.+)}/
> str1.gsub(reg) { |match| $~[:content] }
=> "user.name"
> str2.gsub(reg) { |match| $~[:content] }
=> "[1,2,3].map { |el| el }.join(',')"

Your example didn't work well because [^smth] matches against any single character in the list, not the whole sentence.

BTW I'd like to warn you that regexp might fit for simple adjustments, but it will always have some edge cases. I'm not sure how the example above will behave on interpolation inside interpolation for example.

It's better to use proper lexer & parser for more complex cases.

Also, be very... very careful doing eval

Sign up to request clarification or add additional context in comments.

Comments

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.