Ruby 能保证 eval(str.inspect) == str 吗?

问题描述 投票:0回答:1

我最近发现自己需要根据用户输入生成一个简单的 Ruby 脚本,其中一些需要作为字符串文字包含在脚本中。虽然在我的特定情况下,此输入来自受信任的来源,但我仍然希望以一种不会中断的方式执行此操作,即使输入字符串恰好包含例如引号、反斜杠、换行符、井号或其他意外的元字符。

明显的解决方案(如 this earlier question 的已接受答案中所建议)是使用

String#inspect
方法,其文档说它:

返回 str 的可打印版本,被引号包围,特殊字符被转义。

但是,该文档没有明确说明将

String#inspect
的输出作为 Ruby 代码进行评估将返回原始字符串。而且,事实上,我确实在技术上设法想出了一个使用非 Unicode 字符串的反例:

pry(main)> str = 0x80.chr; eval(str.inspect) == str
=> false

然而,我需要编码的所有字符串都是 Unicode 字符串,所以这个反例对我来说只是理论上的兴趣。但我仍然想要一些书面保证,因此有以下问题:

  1. eval(str.inspect)
    是否保证等于
    str
    ,如果
    str
    是Unicode字符串?
  2. 如果没有,是否有其他方法可以在生成的 Ruby 代码中转义字符串文字, 保证始终有效?

另外,一个奖励问题:

  1. eval("'" + str.gsub(/[\\']/, { "\\" => "\\\\", "'" => "\\'" }) + "'")
    总是保证等于
    str
    吗?
ruby string escaping eval
1个回答
1
投票

如果你想要比

inspect
更明确的保证,有 dump 可以转义所有特殊/不可打印的字符,而 undump 则相反。
str.dump.undump
保证等于
str
。因此,您的脚本生成器可以将
str.dump
作为文字写入文件(保证可打印),然后您可以
eval("dumped string".undump)
.

根据docs,对于您的奖励问题:

除了禁用插值外,单引号字符串还禁用除单引号 (

\'
) 和反斜杠 (
\\
) 之外的所有转义序列。

所以我认为你的 hacky gsub 也可以。

© www.soinside.com 2019 - 2024. All rights reserved.