【问题标题】:How do I parse YAML with nil values?如何使用 nil 值解析 YAML?
【发布时间】:2010-11-21 03:49:00
【问题描述】:

对于我在此处发布的非常具体的问题,我深表歉意,但我希望它能帮助其他可能也遇到此问题的人。我有一个字符串被格式化为以下内容:

[[,action1,,],[action2],[]]

我想把它翻译成有效的 YAML,这样它就可以被解析,看起来像这样:

[['','acton1','',''],['action2'],['']]

我已经尝试了一堆正则表达式来完成这个,但我担心我完全不知所措。如果需要,我可以运行多个表达式。例如(红宝石):

puts s.gsub!(/,/,"','")  # => [[','action1','',']','[action2]','[]]
puts s.gsub!(/\[',/, "['',") # => [['','action1','',']','[action2]','[]]

到了那里,但我有一种感觉,我开始用这种方法陷入困境。有没有更好的方法来做到这一点?

感谢您的帮助!

【问题讨论】:

    标签: ruby regex parsing yaml


    【解决方案1】:

    这对空字段 (ruby1.9) 起作用:

    s.gsub(/(?<=[\[,])(?=[,\]])/, "''")
    

    或者对于不支持零宽度look-behind的ruby1.8:

    s.gsub(/([\[,])(?=[,\]])/, "\\1''")
    

    可以使用以下方法之一引用非空字段:

    s.gsub(/(?<=[\[,])\b|\b(?=[,\]])/, "'")
    s.gsub(/(\w+)/, "'\\1'")
    

    在上面,我使用了零宽度正向向后看和零宽度正向向前看断言('(?

    我查找了一些特定于 ruby​​ 的文档,但找不到任何可以特别解释这些特性的内容。相反,请让我将您推荐给perlre

    【讨论】:

    • 我无法让它工作。我不确定 ruby​​ 是否支持您使用的向后看或向前看语法。我收到以下错误:未定义 (?...) 序列:/(?
    • 啊,我用的是ruby1.9。早期版本可能不支持这些功能。
    • 不,在 1.9 之前不支持开箱即用的lookbehinds。
    • 非常好。感谢您的详细说明。我使用的是 1.8,因此非常感谢这两个版本的附加代码。你是个奇才!
    【解决方案2】:

    只解析它会更容易,然后输出有效的 YAML。


    由于我不懂 Ruby,这里是 Perl 的一个例子。


    由于您只想要 YAML 的一个子集,它看起来类似于 JSON,因此我使用了 JSON 模块。

    我一直想找个借口使用Regexp::Grammars,所以我用它来解析数据。

    我保证不管阵列有多深,它都会起作用。

    #! /usr/bin/env perl
    use strict;
    #use warnings;
    use 5.010;
    #use YAML;
    use JSON;
    use Regexp::Grammars;
    
    
    my $str = '[[,action1,,],[action2],[],[,],[,[],]]';
    
    my $parser = qr{
      <match=Array>
    
      <token: Text>
        [^,\[\]]*
    
      <token: Element>
      (?:
        <.Text>
      |
        <MATCH=Array>
      )
    
      <token: Array>
      \[
         (?:
           (?{ $MATCH = [qw'']; })
         |
           <[MATCH=Element]>   ** (,)
         )
      \]
    }x;
    
    
    if( $str =~ $parser ){
      say to_json $/{match};
    }else{
      die $@ if $@;
    }
    

    哪些输出。

    [["","action1","",""],["action2"],[],["",""],["",[],""]]
    

    如果你真的想要 YAML,只需取消注释“use YAML;”,并将to_json() 替换为Dump()

    ---
    -
      - ''
      - action1
      - ''
      - ''
    -
      - action2
    - []
    -
      - ''
      - ''
    -
      - ''
      - []
      - ''
    

    【讨论】:

    • +1 这是一个非常好的演示。不过,正则表达式方式也适用于深度列表。
    • 我总是发现很难确定正则表达式/替换是否有效,而不仅仅是解析它。
    【解决方案3】:

    试试这个:

    s.gsub(/([\[,])(?=[,\]])/, "\\1''")
     .gsub(/([\[,])(?=[^'\[])|([^\]'])(?=[,\]])/, "\\+'");
    

    编辑:我不确定替换语法。这应该是第一个 gsub 中的第 1 组,第二个中参与人数最多的组 - $+

    【讨论】:

    • 你必须使用 "\\1''" 或 '\1\'\'' 来指代捕获组。
    • 谢谢,我只是在查。
    猜你喜欢
    • 2015-12-06
    • 2015-11-02
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 2019-06-23
    • 2018-10-15
    • 1970-01-01
    • 2020-10-14
    相关资源
    最近更新 更多