在Ruby中最好的方法来逃避和unescapestring?
Ruby是否有任何内置的方法来转义和转义string? 在过去,我使用正则expression式; 然而,我发现Ruby可能会一直在内部进行这样的转换。 也许这个function暴露在某个地方。
到目前为止,我已经提出了这些function。 他们工作,但他们似乎有点hacky:
def escape(s) s.inspect[1..-2] end def unescape(s) eval %Q{"#{s}"} end
有没有更好的办法?
如果您不想使用eval
,但愿意使用YAML
模块,则可以使用它:
require 'yaml' def unescape(s) YAML.load(%Q(---\n"#{s}"\n)) end
YAML
优于eval
的优势在于它可能更安全。 cane
不允许使用eval
。 我已经看到了使用$SAFE
和eval
,但目前尚不能通过JRuby获得。
对于什么是值得的,Python确实对反斜杠进行了原生支持。
有一些逃避方法,其中一些:
# Regexp escapings >> Regexp.escape('\*?{}.') => \\\*\?\{\}\. >> URI.escape("test=100%") => "test=100%25" >> CGI.escape("test=100%") => "test%3D100%25"
所以,这要看你需要解决的问题。 但我会避免使用检查逃脱。
更新 – 有一个转储,检查使用,它看起来就是你所需要的:
>> "\n\t".dump => "\"\\n\\t\""
Caleb函数是最接近的String #inspect相反我能find,但它包含两个错误:
- \\处理不当。
- \ x ..保留了反斜杠。
我修复了上面的错误,这是更新后的版本:
UNESCAPES = { 'a' => "\x07", 'b' => "\x08", 't' => "\x09", 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c", 'r' => "\x0d", 'e' => "\x1b", "\\\\" => "\x5c", "\"" => "\x22", "'" => "\x27" } def unescape(str) # Escape all the things str.gsub(/\\(?:([#{UNESCAPES.keys.join}])|u([\da-fA-F]{4}))|\\0?x([\da-fA-F]{2})/) { if $1 if $1 == '\\' then '\\' else UNESCAPES[$1] end elsif $2 # escape \u0000 unicode ["#$2".hex].pack('U*') elsif $3 # escape \0xff or \xff [$3].pack('H2') end } end # To test it while true line = STDIN.gets puts unescape(line) end
YAML的::unescape
似乎没有逃避引号字符,例如'
和"
。我猜这是devise,但这让我伤心。
你绝对不想在任意或客户端提供的数据上使用eval
。
这是我用的。 处理我见过的所有东西,不会引入任何依赖关系。
UNESCAPES = { 'a' => "\x07", 'b' => "\x08", 't' => "\x09", 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c", 'r' => "\x0d", 'e' => "\x1b", "\\\\" => "\x5c", "\"" => "\x22", "'" => "\x27" } def unescape(str) # Escape all the things str.gsub(/\\(?:([#{UNESCAPES.keys.join}])|u([\da-fA-F]{4}))|\\0?x([\da-fA-F]{2})/) { if $1 if $1 == '\\' then '\\' else UNESCAPES[$1] end elsif $2 # escape \u0000 unicode ["#$2".hex].pack('U*') elsif $3 # escape \0xff or \xff [$3].pack('H2') end } end
Ruby的inspect
可以帮助:
"a\nb".inspect => "\"a\\nb\""
通常情况下,如果我们打印一个embedded式换行的string,我们会得到:
puts "a\nb" a b
如果我们打印检查版本:
puts "a\nb".inspect "a\nb"
将检查的版本分配给一个variables,并且你将得到该string的转义版本。
要撤销转义,请eval
string:
puts eval("a\nb".inspect) a b
我真的不喜欢这样做。 这比我在实践中要做的事情更加好奇。
我怀疑Shellwords.escape
会做你想要的
https://ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape