【问题标题】:YAML (Ruby) loading "on" as trueYAML(Ruby)加载“on”为真
【发布时间】:2015-04-14 22:38:22
【问题描述】:

我正在尝试从 YAML 文件加载单词列表。在文件中有一个条目

- on

Ruby 将其加载为“true”,而不是“on”。类似地,“off”被加载为“false”。对 Psych 代码的快速检查显示“是”和“否”的处理方式相同。

除了在开关周围添加引号之外,我有什么办法可以改变这种行为?

如果我读取文件并解析,而不是 load_file,我就能看到这些值。

# test.yaml
- true
- false
- yes
- no
- on
- off
- y
- n
- Y
- N

我通过解析而不是加载获得了一个 Psych 文档,其中包含转换为原生之前的文本。

YAML.parse_file('test.yaml')

想知道如何正确提取它。

来自文档

“表示阶段是指已组合成 YAML::BaseNode 对象的数据。在此阶段,文档以节点对象树的形式提供。您可以在此级别执行 YPath 查询和转换。(请参阅 YAML: :解析。)"

在编写全面的 YPath 查询以提取数据方面需要帮助。

(PS:这可能看起来有点迂回,但这为我清理了很多数据管理方面的事情)

【问题讨论】:

  • 你有编辑yaml文件的权限吗?

标签: ruby yaml


【解决方案1】:

这似乎符合我目前的要求。

require 'yaml'

ydoc = YAML.parse_file('test.yaml')
puts ydoc.children.map { |sequence| sequence.children.map { |scalar| scalar.value }}

“孩子”有助于从心理文档>心理序列>心理标量向下移动。

请让我知道你的 cmets。

【讨论】:

    【解决方案2】:

    正如其他答案中已经解释的那样,on 被视为“真实”值。这种行为是intentionally coded in Psych

    正如 Arup Rakshit 和 Mikhail P 所解释的,该问题的最佳解决方案是引用该值。但是,鉴于您的问题要求替代方案,这里有一个替代方案。

    Psych 中的标量转换在 Psych::ScalarScanner#tokenize 中进行了硬编码。一个可能(但强烈不鼓励)的选项是猴子修补此方法以更改此case statement

        when /^(yes|true|on)$/i
          true
        when /^(no|false|off)$/i
          false
    

    您可能会意识到查看源代码,该方法很长,并且猴子补丁会迫使您复制/粘贴一大块代码。没有简单的方法,选项被硬编码到选择案例中(另一个迹象表明这不是一个好主意)。

    就个人而言,我永远不会那样做。修改 Psych 的核心行为可能会导致一些意想不到的副作用,因为其他库可能依赖于这种行为。


    如果您不想物理修改原始文件,另一种选择是编写一个在运行时更改它的代理。

    在实践中,您可以创建一个 CustomYaml 解析器,它实现了 parse_file 方法。该方法将读取内存中文件的内容,将任何出现的未转义on“搜索和替换”为"on",然后感受YAML.load()

    这将欺骗YAML 解析,使其将每个“on”标记解释为标量字符串。

    与这种预处理方式类似,您可以通过遍历 Psych 返回的 YAML AST 来采用后处理方式。

    【讨论】:

    • 进行预处理是一种选择。谢谢!
    • 如果 YAML 参考卡(参见 Mikhail P 的帖子)是基础,那么 Psych 会省略“Y”和“N”。
    【解决方案3】:

    按照您的提示修改 AST 使其工作。

    代码如下:

    src = YAML.parse(data)
    src.select{ |node| node.is_a?(Psych::Nodes::Scalar) &&
                       %w(on off).include?(node.value) }
      .each{|node| node.quoted = true }
    

    所以基本上,这只是诱使系统认为所有值为onoff 的值节点都被引用了。这使它们看起来像字符串。

    当然,这取决于实现,对于 Psych 以外的其他人来说,这必须以不同的方式完成。

    【讨论】:

    • 我想我现在有了更简单的版本,只是为了满足我目前的需求。但是,在更一般的情况下,我们可能不得不这样做。
    【解决方案4】:

    它在 YAML reference card 中列出,但我在规范中找不到任何引用。

    与语言无关的标量类型: ... { Y, true, Yes, ON } : Boolean true { n, FALSE, No, off } : 布尔假 ...

    我认为引号是你唯一的选择。

    【讨论】:

    • 有趣! Y 和 n 在 Psych 中没有实现为布尔值。
    • 仅供参考,在 YAML 1.2 规范(当前版本)中删除了 true/false 的 yes/no 别名。这可能就是你看不到它的原因。它在 YAML 1.1 中,我猜有些包仍然支持 1.1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2010-11-16
    • 2012-08-21
    • 1970-01-01
    • 2016-08-05
    • 2014-12-06
    • 2020-11-06
    相关资源
    最近更新 更多