为什么这只返回第一个设置?

时间:2013-03-29 13:04:25

标签: ruby

我开始研究Ruby,并认为我会构建一些东西;我开始在其中编写一个简单的配置文件解析器。简单的原则是你为它提供一个格式正确的文件,它会吐出一个设置的哈希值。例如,这是一个配置文件:

localhost: 4000;
auto: true;

这就是它回馈的内容:

{"localhost" => "4000", "auto" => "true"}

现在,当使用以下代码直接输入时,我可以使用它:

  def spit_direct(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      if input.include? arg
        strip = input.match(/#{arg}:\s(\w*);/)
        spat[arg] = strip[1]
      else
        # error message
        break
      end
    end
    spat
  end

  spit_direct("localhost: 4000; auto: true;", "localhost", "auto")
  # => {"localhost"=>"4000", "auto"=>"true"}

这可以按照我想要的方式工作,但是如果可以输入实际文件会更好。我提出了以下代码,但它似乎只返回第一个设置,而不是第二个设置:

  def spit_file(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      File.open(input).each_line do |line|
        if line.include? arg
          strip = line.match(/#{arg}:\s(\w*);/)
          spat[arg] = strip[1]
        else
          # error message
          break
        end
      end
    end
    spat
  end

如果我提供一个名为config.cnfg的文件,其内容与上述几个设置文件相同,如下所示:

spit_file("(path)/config.cnfg", "localhost", "auto")

它只返回:

# => {"localhost"=>"4000"}

为什么会这样?昨晚我花了几个小时才看到它,但似乎无法弄清问题是什么。

2 个答案:

答案 0 :(得分:3)

你做错了。对于args中的每个arg,再次打开文件,如果该文件的第一行与arg匹配,则更新哈希,然后关闭文件,否则立即关闭文件。

反转循环嵌套:

def spit_file(input = "", *args)
  spat = Hash.new
  File.open(input).each_line do |line|
    args.each do |arg|
      if line.include? arg
        strip = line.match(/#{arg}:\s(\w*);/)
        spat[arg] = strip[1]
      end
    end
  end
  spat
end


1.9.3p327 :001 > spit_file('cfg.cfg', 'localhost', 'auto')
 => {"localhost"=>"4000", "auto"=>"true"}

答案 1 :(得分:1)

您的代码可以在没有该break语句的情况下运行。它打破了args.each循环而不是each_line循环。第一次一行没有你所在的精确arg时,循环就会中断。您应该使用下一个语句。

def spit_file(input = "", *args)
    spat = Hash.new
    args.each do |arg|
      File.open(input).each_line do |line|
        if line.include? arg
          strip = line.match(/#{arg}:\s(\w*);/)
          spat[arg] = strip[1]
        else
          # error message
          next
        end
      end
    end
    spat
  end