AKA如何使用正则表达式找到未转义的字符序列?
给定环境设置:
@secret = "OH NO!"
$secret = "OH NO!"
@@secret = "OH NO!"
并从一个看起来像这样的文件中读取字符串:
some_str = '"\"#{:NOT&&:very}\" bad. \u262E\n#@secret \\#$secret \\\\#@@secret"'
我想将此评估为Ruby字符串,但没有插值。因此,结果应该是:
puts safe_eval(some_str)
#=> "#{:NOT&&:very}" bad. ☮
#=> #@secret #$secret \#@@secret
相比之下,eval
- 仅解决方案产生
puts eval(some_str)
#=> "very" bad. ☮
#=> OH NO! #$secret \OH NO!
起初我试过了:
def safe_eval(str)
eval str.gsub(/#(?=[{@$])/,'\\#')
end
但是在上面的恶意中间案例中失败了,产生了:
#=> "#{:NOT&&:very}" bad. ☮
#=> #@secret \OH NO! \#@@secret
答案 0 :(得分:1)
你可以通过regex来做到这一点,确保在你想要逃脱的角色之前有一个偶数个反斜杠:
def safe_eval(str)
eval str.gsub( /([^\\](?:\\\\)*)#(?=[{@$])/, '\1\#' )
end
...说:
[^\\]
(?:\\\\)
*
#
字符{
,@
或$
字符。#
答案 1 :(得分:1)
根本不使用eval怎么样?根据聊天中的this评论,所有必要的内容都是转义引号,换行符和unicode字符。这是我的解决方案:
ESCAPE_TABLE = {
/\\n/ => "\n",
/\\"/ => "\"",
}
def expand_escapes(str)
str = str.dup
ESCAPE_TABLE.each {|k, v| str.gsub!(k, v)}
#Deal with Unicode
str.gsub!(/\\u([0-9A-Z]{4})/) {|m| [m[2..5].hex].pack("U") }
str
end
当你的字符串被调用时,结果是(在你的变量环境中):
"\"\"\#{:NOT&&:very}\" bad. ☮\n\#@secret \\\#$secret \\\\\#@@secret\""
虽然我宁愿不必特别处理unicode,但这是唯一不用eval
的方法。