Why does this only return the first setting?

匿名 (未验证) 提交于 2019-12-03 00:44:02

问题:

I started looking into Ruby and thought I'd build something; I started writing a simple configuration file parser in it. The simple principle is that you feed it a properly formatted file, and it spits out a hash of the settings. For example, this is a config file:

localhost: 4000; auto: true; 

and this is what it gives back:

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

Now, I have got it to work when this is entered directly with the following code:

  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"} 

This works as I want it to however I though it would be better if an actual file could be fed. I came up with the following code however it only seems to return the first setting, and not the second one:

  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 

If I feed it a file called config.cnfg with the same contents as the above couple of setting files, like so:

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

It only returns:

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

Why is that? I've spent couple of hours on it last night but can't seem to figure out what the problem.

回答1:

You're doing it wrong. For each arg in args, you open the file again, and if the first line of this file matches the arg, then the hash gets updated, and then the file gets closed, otherwise, the file gets closed immediately.

Invert the loops nesting:

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"} 


回答2:

Your code would work without that break statement. It breaks out of the args.each loop and not the each_line loop. The first time a line does not have the exact arg that you are on, the loop breaks. You should use a next statement instead.

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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!