#coding=utf-8 require "aio/core" class Aio::Module::InputStyle::Console < Aio::Module::InputStyle include Aio::Module include Aio::Ui::Verbose class Machine attr_accessor :regs, :state def initialize @cmd_state = CmdState.new(self) @context_state = ContextState.new(self) @empty_state = EmptyState.new(self) @cmd_context = CmdContext.new @state = @empty_state end def state @state.class end def cmd_context @cmd_context end def to_cmd_state @state = @cmd_state end def to_context_state @state = @context_state end def to_empty_state @state = @empty_state end def parse_line(line) @state.parse_line(line) end end class CmdContext attr_accessor :device_name, :cmd, :context # all_info = [[device_name, cmd, context] ... ] attr_accessor :all_info def initialize @device_name = "" @cmd = "" @context = [] @all_info = [] end def done # 当之前有cmd内容的时候,比较两个的长度 # 长的保留 info_idx = has_cmd? if info_idx if @all_info[info_idx][2].size < context.size @all_info[info_idx][2] = context end else # 如果都没有,那么就直接添加 @all_info << [device_name, cmd, context] end self.clear end def has_cmd? @all_info.each_with_index do |info, idx| next unless info[1] == device_name return idx if info[2] == cmd end return nil end def clear @device_name = "" @cmd = "" @context = [] end end class State include Aio::Ui::Verbose def initialize(machine) @machine = machine end def cmd_context @machine.cmd_context end end class EmptyState < State def parse_line(line) # 当前是空的状态 # 判断当前行有没有模块中的命令 line = Aio::Base::Toolkit::String.safe(line) return unless @machine.regs.match(line) @machine.to_cmd_state @machine.parse_line(line) end end class CmdState < State def parse_line(line) # 判断是不是cmd命令行 res = /^[\[|<]?(?.*)(#|>|\])(?.*)/.match(line) if res.nil? @machine.to_empty_state return end # 当已经发现了是cmd行,那么紧接下来就是收集文本内容 cmd_context.device_name = res[:name] cmd_context.cmd = res[:cmd] @machine.to_context_state end end class ContextState < State def parse_line(line) # 如果这行是命令行格式,那么就代表上一个cmd内容结束 tmp_reg = ::Regexp.new "^[\\[|<]?#{cmd_context.device_name}(#|>|\\])" # 可能会出现UTF-8识别不出摄氏度符号的问题 # 已经通过安全字符解决 begin if tmp_reg.match(line) cmd_context.done # 完成后将状态设置为空,并且重新分析这一行 # 毕竟如果这行也cmd行呢 @machine.to_empty_state return @machine.parse_line(line) end rescue => e print_error cmd_context.device_name + " 设备巡检信息编码出现问题" print_error line + " : " + e.message end cmd_context.context << line end end def initialize super({ :author => "Elin", :description => "这个模块用于对命令行格式的输入处理", :platform => "all", }) @machine = Machine.new end def parse dir = self.input_file dir_pn = Pathname.new(dir) # 加载所有的cmd正则表达式 @machine.regs = merge_regs(ext_info[:cmds_reg]) # 如果是单个文件的话,直接进入文件解析模式 if dir_pn.file? parse_file(dir_pn) else # 如果是文件夹的话,那么就对每个文件进行解析 Find.find(dir) do |file| fn = Pathname.new(file) parse_file(file) if fn.file? end end @machine.cmd_context.all_info.each do |info| yield info[0], info[1], info[2] end end def parse_file(file) fo = File.open(file, "r+", :encoding => "utf-8") fo.each_line do |line| begin line = Aio::Base::Toolkit::String.safe(line) line = line.strip rescue => e print_error line + " : " + e.message end @machine.parse_line(line) end # 如果最后没有done结束,则手动结束 if @machine.state == ContextState @machine.cmd_context.done end end def merge_regs(arr_regs) regs = Aio::Base::Toolkit::Regexp.merge(arr_regs).to_s regs.gsub!('(^', '(') ::Regexp.new(regs) end end