Ruby 关于固定格式的文本解析

big_bugs · 2015年01月16日 · 最后由 luikore 回复于 2015年01月19日 · 2083 次阅读

目前项目要求解析被采集的设备上的配置文件,文件格式如下

interfaces {
 ge-1/0/1 {
        description pT:CQ-GYQ-WLD-BAS-2.MAN.ME60-X16.163:1GE::ETH-8/1/2;
        vlan-tagging;
        mtu 9192;
        hold-time up 60000 down 0;
        link-mode full-duplex;
        gigether-options {
            no-auto-negotiation;
        }
        unit 2 {
            vlan-id 2;
            family inet {
                address 58.43.34.105/30;
            }
        }
        unit 3 {
            vlan-id 3;
            family inet {
                address 172.1.1.33/30;
            }
        }
    }
}

大概想得到的内容格式就是设备->端口->单元->组,ip

{:interfaces => {:port_1 =>{:unit_1 => "address_1" ,:unit_2 => "address_2" }}}

不知道有木有简便一点的方法,怎么样才能按 { } 的层次解析出想要的信息呢

你得写个 parser, 例如用我的 rsec...

require "rsec"

module Parser
  include Rsec::Helpers
  extend self

  def build_parser
    names = /[^\{\s;]+/.r.join(/[\ \t]+/).even

    entry = seq(names, ';'.r | (/\s*/.r >> lazy{block})).map{|(vs, last_v)|
      last_v == ';' ? vs : vs << last_v
    }

    block = /\{\s*/.r >> entry.join(/\s*/).even << (/\s*\}/)

    entry
  end

  def parse src
    @parser ||= build_parser
    @parser.parse! src.strip
  end
end

if __FILE__ == $PROGRAM_NAME
  require "pp"
  pp Parser.parse DATA.read
end

__END__
interfaces {
    ge-1/0/1 {
        description pT:CQ-GYQ-WLD-BAS-2.MAN.ME60-X16.163:1GE::ETH-8/1/2;
        vlan-tagging;
        mtu 9192;
        hold-time up 60000 down 0;
        link-mode full-duplex;
        gigether-options {
            no-auto-negotiation;
        }
        unit 2 {
            vlan-id 2;
            family inet {
                address 58.43.34.105/30;
            }
        }
        unit 3 {
            vlan-id 3;
            family inet {
                address 172.1.1.33/30;
            }
        }
    }
}

@luikore 要解析的文件很长 放到 string 会溢出

#2 楼 @big_bugs 多长?1GB 以上就用状态机吧

需要 登录 后方可回复, 如果你还没有账号请 注册新账号