まえに、iniFileを読むためのRubyのクラスを実装したのを書いたけれど、ちょっと直しました。以前のものは、指定した、セクション、キーが存在しない場合、""を返すようにしていたのですが、Rubyっぽく、nilを返すようにしました。
iniH = IniFile.new( fileSpec)
でファイルから読み、
hash = iniH[ section名 ]
でセクション全体をハッシュで返します。セクションがない場合、nilが返ります。
セクションの有無を確認の上、キーにアクセスするには、
raise "NO section" if ! iniH[ セクション名 ]
value = iniH[セクション名][キー名]
のようにします。
新たにセクション、キーを指定して値を追加する場合には、
(iniH[ セクション名] || iniH[ セクション名] = Hash.new)[key名] = 値
みたいになります。ほとんどパズルみたいなので、[], []=を定義しなおしてみました。これで、
val = iniH[ セクション名, キー名]
と書くことができます。目的とするセクションや、キーがない場合はnilが返ります。
また、
iniH[ セクション名、 キー名 ] = value
という、書き方ができます。この場合、指定したセクションが存在しない場合は、新たにセクションを追加し、キーにvalueを関連付けます。
それよりも嵌ったのは、正規表現で、キーと値の抽出は、/(.*)=(.*)/ではなく、/(.*?)=(.*)/,つまり最短一致にしておかないとちょっと動作がまずそうです。
#
# (c)2009 BO
# inifile
#
class IniFile < Hash
@@ReComment = /^#/
@@ReSection =/\[(.*)\]/
@@ReKeyValue =/(.*?)=(.*)/
def initialize( fileSpec = nil )
if fileSpec
File::open( fileSpec) {|f|
sectionName = ""
while line = f.gets
if line =~ @@ReComment # skip a line
elsif line =~ @@ReSection
sectionName = $1.strip
elsif line =~ @@ReKeyValue
self[ sectionName, $1.strip] = $2.strip if sectionName != ""
end
end # while
}
end
end #def initialize( fileSpec = nil )
def write2File( fileSpec )
fp = File.open( fileSpec ,'w')
fp.print to_s()
fp.close
end #def write2File( filespec )
def to_s
str = String.new
self.each_key{ |section|
str += "[#{section}]\n"
if self[section]
self[section].each_key{|key|
str += "#{key}=#{self[section][key]}\n" if self[section][key]
}
end
}
str
end #def to_s
def []( section, *rest)
return super(section) if rest.length == 0
key=rest[0]
self[section] ? self[section][key] : nil
end # def []( section, *rest)
def []=( section, *rest )
if rest.length == 1
hash = rest[0]
return super( section, hash)
elsif rest.length == 2
key, val = rest[0], rest[1]
return (self[section] || super(section, Hash.new))[ key ]= val
else
raise "invalid number of param"
end
end #def []=( section, *rest )
end # class IniFile