变量魔术和从文件中读取

时间:2009-10-16 11:34:41

标签: ruby file variables

假设我有以下文件( input.txt ):

name = "Peter"
age = 26
family_status = married

提到的行可以按随机顺序存储,谎言:

family_status = married
name = "Peter"
age = 26

在我的计划中,我还有变量 family_status 年龄名称。如何在一个循环中从文件中读取这些行并使用值<?p>分配对应的变量

3 个答案:

答案 0 :(得分:4)

设置变量

这取决于几个事实。

  • 您拥有什么样的变量(局部变量,实例变量,类变量或全局变量)
  • family_status是哪种类型(String, Symbol,无论如何)

我假设您正在使用实例变量:

def read_vars(io, vars)
  io.each do |line|
    # ensure the line has the right format (name = var)
    raise "wrong format" unless line=~ /^\s*(\w+)\s*=\s*"?(.*?)"?\s+$/
    var= :"@#{$1}"
    # pick the type of the data
    value= case vars[var]
    when String
      $2
    when Integer
      $2.to_i
    when Symbol
      $2.to_sym
    else
      raise "invalid var"
    end
    instance_variable_set(var, value)
  end
end

read_vars(File.read("input.txt", :@age => Integer, :@name => String, :@family_status => Symbol )

如果您不使用实例变量,则必须根据需要更改instacne_variable_setvar= :"@...行。此代码具有以下优点:

  • 您可以控制可以设置的变量
  • 您可以控制这些变量的类型
  • 您可以轻松添加新变量和/或更改变量类型,而无需更改读取代码
  • 您可以使用此代码读取完全不同的文件,而无需为其编写新代码

读为YAML

如果您的需求不像您的问题那样具体,我会采取完全不同的方法。

我会将input.txt写为yaml文件。在yaml语法中,它看起来像这样:

---
name: Peter
age: 26
family_status: :married

您可以阅读:

YAML.load(File.read("input.txt")) # => {"name" => "Peter", "age" => 26, "family_status" => :married }

如果您不控制input.txt文件,请注意,您不能控制数据的类型。我将文件命名为input.yaml而不是input.txt。如果您想了解更多信息,关于如何编写yaml文件请查看:http://yaml.kwiki.org/?YamlInFiveMinutes。关于yaml和ruby的更多信息可以在http://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/index.html找到。

答案 1 :(得分:2)

假设该文件与您的示例一样正常,您可以将所有内容混合成一个漂亮的哈希:

input = IO.read("input.txt")
input_hash = Hash[*input.gsub(/"/,"").split(/\s*[\n=]\s*/)]

这会给你:

=> {"name"=>"Peter", "family_status"=>"married", "age"=>"26"}

但是你真的需要一些特定于变量的代码来做你想要的任何类型处理,特别是对于family_status来说......

答案 2 :(得分:0)

你可以试试这个。通过以下方式不是很好:

class Test
  attr_accessor :name, :age, :family_status

  def load
    File.foreach('input.txt') do |line|
      match = line.match /^(\S+)\s*=\s*"?(\S+?)"?\s*$/
      self.send("#{match[1]}=", match[2]) if match
    end
  end
end

test = Test.new
test.load