How do I read/write an ini file in ruby. I have an ini file that I need to
如何在ruby中读/写一个ini文件。我有一个我需要的ini文件
- read
- change an entry
- write out to a different location
改变一个条目
写到不同的位置
How would I do that in ruby? The documentation on this is bleak.
我怎么能用红宝石做到这一点?关于这方面的文件很惨淡。
6 个解决方案
#1
10
I recently used ruby-inifile. Maybe it's overkill compared to the simple snippets here...
我最近使用ruby-inifile。与这里的简单片段相比,这可能是过度杀伤...
#2
11
Use the InIFile Gem
As @method said, use the inifile gem. There is also an ini gem but I haven't used it.
正如@method所说,使用inifile gem。还有一个ini宝石,但我没有使用它。
I found the documentation here a slightly more helpful than the documentation here which is where the gem page links to.
我发现这里的文档比这里的文档更有帮助,这是gem页面链接到的地方。
There were not many examples so here is a bit of code to get you started:
没有太多的例子,所以这里有一些代码可以帮助你入门:
Example Setup
First, create a file /tmp/desktop.ini
with these contents:
首先,使用以下内容创建文件/tmp/desktop.ini:
[Desktop Entry]
Version=1.0
Type=Application
Name=Foo Viewer
Comment=The best viewer for Foo objects available!
TryExec=fooview
Exec=fooview %F
Icon=fooview
Make sure you have run gem install inifile
from the command line.
确保从命令行运行gem install inifile。
Example Code
Create a file like /tmp/ini-test.rb
with these contents:
使用以下内容创建/tmp/ini-test.rb之类的文件:
require 'inifile'
require 'pp'
# read an existing file
file = IniFile.load('/tmp/desktop.ini')
data = file["Desktop Entry"]
#output one property
puts "here is one property:"
puts data["Name"]
# pretty print object
puts "here is the loaded file:"
pp file
# create a new ini file object
new_file = IniFile.new
# set properties
new_file["Desktop Entry"] = {
"Type" => "Application",
"Name" => 'test',
"Exec" => 'command',
}
# pretty print object
puts "here is a object created with new:"
pp new_file
# set file path
new_file.filename = "/tmp/new_ini_file.ini"
# save file
new_file.write()
puts "the new object has been saved as a file to /tmp/new_ini_file.ini"
Example Results
Running that file with ruby /tmp/ini-test.rb
should yield something like:
使用ruby /tmp/ini-test.rb运行该文件应该会产生如下内容:
here is one property:
Foo Viewer
here is the loaded file:
{ this output hidden for brevity }
here is a object created with new:
#<IniFile:0x007feeec000770
@comment=";#",
@content=nil,
@default="global",
@encoding=nil,
@escape=true,
@filename=nil,
@ini=
{"Desktop Entry"=>
{"Type"=>"Application",
"Name"=>"test",
"Exec"=>"command",
"Icon"=>"icon_filename",
"Comment"=>"comment"}},
@param="=">
the new object has been saved as a file to /tmp/new_ini_file.ini
Modify as required suit your needs.
根据需要修改以满足您的需求。
#3
2
Here's the module for reading and writing of .ini-files with as less change to original file as possible (for files which read humans and machines):
这是用于读取和写入.ini文件的模块,尽可能少地更改原始文件(对于读取人和机器的文件):
class IniFileExc < RuntimeError
end
class IniNode def initialize(name, value=nil) @line_start = -1; @line_end = -1; @level = 0; @name = name; @value = value; @keys = {}; @keylist = []; @modified = false; @deleted = false; end attr_reader :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted attr_writer :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted
class iniNode def initialize(name,value = nil)@line_start = -1; @line_end = -1; @level = 0; @name = name; @value = value; @keys = {}; @keylist = []; @modified = false; @deleted = false; end attr_reader:level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted attr_writer:level,:line_start,:line_end,:name,:value,:keylist,:keys, :改性,:删除
def to_str return @name.to_s + ' = ' + @value.to_s; end
def to_str return @ name.to_s +'='+ @ value.to_s;结束
def to_s return @value.to_s; end def to_i return @value.to_i end def to_f return @value.to_f; end
def to_s return @ value.to_s; end def to_i return @ value.to_i end def to_f return @ value.to_f;结束
def insert(key, nil); return @keys[key]; end
def insert(key,nil); return @keys [key];结束
def insert(key, value) return false if (@keys.has_key?(key)); node = nil; if (value && ((value.class == IniNode) || (value.class == IniSection))) node = value; else if (@level <= 0) node = IniSection.new(key); else node = IniNode.new(key, value) end end node.line_start = @line_end + 1 if (node.line_start < 0); node.level = @level + 1; @keys[key] = node; @keylist.push(key); return true; end
def insert(key,value)返回false if(@ keys.has_key?(key)); node = nil; if(value &&((value.class == IniNode)||(value.class == IniSection)))node = value; else if(@level <= 0)node = IniSection.new(key); else node = IniNode.new(key,value)end end node.line_start = @line_end + 1 if(node.line_start <0); node.level = @level + 1; @keys [key] = node; @ keylist.push(键);返回true;结束
def []=(key, value) rc = insert(key, value); @keys[key].value = value; @keys[key].modified = true; @modified = true; end
def [] =(键,值)rc = insert(键,值); @keys [key] .value = value; @keys [key] .modified = true; @modified = true;结束
def delete(key) return false if (! @keys.has_key?(key)); @keys[key].deleted = true; @modified = true; end end
def delete(key)如果返回false(!@ keys.has_key?(key)); @keys [key] .deleted = true; @modified = true;结束
class IniSection < IniNode def initialize(name) super(name); end
class IniSection
def to_str return ('[' + @name + ']'); end end
def to_str return('['+ @name +']');结束
class IniFile < IniNode
def initialize(path, load=true)
super(path);
@lines = [];
reload() if (load);
end
def reload begin input = File.new(@name, "r"); rescue raise; else prevnode = node = self; lineno = 0; input.each do |line| @lines.push(line); parsed_node = parse_line(lineno, line); if (parsed_node); if (parsed_node.class == IniSection) if (parsed_node != node) prev_node = node; node = parsed_node; insert(node.name, node); prev_node.line_end = lineno - 1; end else node.insert(parsed_node.name, parsed_node); end end lineno += 1; end input.close;
def reload begin input = File.new(@ name,“r”);救援;否则prevnode = node = self; lineno = 0; input.each do | line | @ lines.push(线); parsed_node = parse_line(lineno,line); if(parsed_node); if(parsed_node.class == IniSection)if(parsed_node!= node)prev_node = node; node = parsed_node; insert(node.name,node); prev_node.line_end = lineno - 1; end else node.insert(parsed_node.name,parsed_node); end end lineno + = 1;结束input.close;
node.line_end = @line_end = lineno - 1;
end
end
def parse_line(lineno, line) return nil if (line =~ /^\s*$/); return nil if (line =~ /^\s*#/); return nil if (line =~ /^\s*;/); if (line =~ /^\s*[\s*(.+)\s*].$/) rv = IniSection.new($1); rv.line_start = lineno; rv.level = @level + 1; return rv; elsif (line =~ /^\s(\S?.[^=\s])\s=\s*(\S?[^#;][^#;\s\n]).$/) rv = IniNode.new($1, $2); rv.line_start = rv.line_end = lineno; rv.level = @level + 2; return rv; end return nil; end
def parse_line(lineno,line)返回nil if(line =〜/ ^ \ s * $ /); return nil if(line =〜/ ^ \ s *#/); return nil if(line =〜/ ^ \ s *; /); if(line =〜/^\s* [\s*(.+)\s*].$/)rv = IniSection.new($ 1); rv.line_start = lineno; rv.level = @level + 1;返回rv; elsif(line =〜/^ \ s (\S?。[^ = \ ss])\s=\s*(\S?[^#;][^#;\s\n]).$/) rv = IniNode.new($ 1,$ 2); rv.line_start = rv.line_end = lineno; rv.level = @level + 2;返回rv;结束回报无;结束
def write inserted = {}; @keylist.each do |sect| sectnode = @keys[sect]; next if (!sectnode.modified || sectnode.deleted); if (sectnode.line_end < 0) @lines.push("\n"); @lines.push(sectnode.to_str + "\n"); end sectnode.keylist.each do |key| keynode = sectnode.keys[key]; next if (!keynode.modified || keynode.deleted); if (keynode.line_end < 0) if (sectnode.line_end < 0) @lines.push(keynode.to_str + "\n"); else idx = sectnode.line_end.to_i; inserted[idx] = [] if (! inserted.has_key?(idx)); inserted[idx].push(keynode.to_str); end else line = @lines[keynode.line_start]; if (line =~ /^(\s*)(\S?.[^=\s]\s=\s*\S?.+[^#;\s])(\s*[#;].)$/) line = $1 + keynode.to_str + $3 + "\n"; else line = line.gsub(/^(\s)(\S?.[^=\s]\s=\s*\S?[^#;]+[^#;\n\s])(.*)$/){ $1 + keynode.to_str + $3}; end @lines[keynode.line_start] = line; end end end
def write inserted = {}; @ keylist.each do | sect | sectnode = @keys [sect]; next if(!sectnode.modified || sectnode.deleted); if(sectnode.line_end <0)@ lines.push(“\ n”); @ lines.push(sectnode.to_str +“\ n”);结束sectnode.keylist.each do | key | keynode = sectnode.keys [key]; next if(!keynode.modified || keynode.deleted); if(keynode.line_end <0)if(sectnode.line_end <0)@ lines.push(keynode.to_str +“\ n”); else idx = sectnode.line_end.to_i; inserted [idx] = [] if(!inserted.has_key?(idx));插入[IDX] .push(keynode.to_str); end else line = @lines [keynode.line_start]; if(line =〜/^(\s*)(\??????????? 。)$ /)line = $ 1 + keynode.to_str + $ 3 +“\ n”; else line = line.gsub(/ ^(\ s)(\ S?。[^ = \ s] \ s = \ s * \ S?[^#;] + [^#; \ n \ s])( 。*)$ /){$ 1 + keynode.to_str + $ 3}; end @lines [keynode.line_start] = line;最终结束
deleted = {};
@keylist.each do |sect|
sectnode = @keys[sect];
next if (!sectnode.deleted && !sectnode.modified);
if (sectnode.deleted && (sectnode.line_start >= 0) && (sectnode.line_end >= 0) \
&& (sectnode.line_end >= sectnode.line_start))
for i in sectnode.line_start..sectnode.line_end
deleted[i] = true;
end
end
sectnode.keylist.each do |key|
keynode = sectnode.keys[key];
next if (!keynode.deleted);
deleted[keynode.line_start.to_i] = true \
if ((keynode.line_start >= 0) && (keynode.line_end >= 0) && (keynode.line_start == keynode.line_end));
end
end
begin
file = File.new(@name, 'w');
rescue
raise(IniFileExc, "Failed to open " + @name + " for writing: #{$!}", caller);
else
cnt = -1;
@lines.each do |line|
cnt += 1;
if (inserted.has_key?(cnt))
inserted[cnt].each do |ins|
file.puts(ins + "\n");
end
end
next if (deleted[cnt]);
file.puts(line);
end
file.close;
end
end end
Usage example:
begin
ini = IniFile.new('file.ini');
ini['common']['param'] = 'value';
ini['common'].delete('unused_param');
ini.delete('unused_section');
print "Valuable value: ", ini['common']['param'], "\n";
ini.write;
rescue IniFileExc
print "Oh, that's not good: ", $!, "\n";
end
Hope this helps.
希望这可以帮助。
#5
0
If I understand correctly,
如果我理解正确,
outFile = File.new('out.ini', 'w')
File.open('in.ini', 'r') do |inFile|
inFile.each_line do |line|
# foo is the entry you want to change, baz is its new value.
outFile.puts(line.sub(/foo=(.*)/, 'foo=baz'))
end
end
outFile.close
Note that when you use File.open
with a block, the file will automatically be closed when the block terminates.
请注意,将File.open与块一起使用时,该块将在块终止时自动关闭。
#6
-4
file = File.new("your.ini", "r")
while (line = file.gets)
puts "#{line}" #additionally make changes
end
file.close
#1
10
I recently used ruby-inifile. Maybe it's overkill compared to the simple snippets here...
我最近使用ruby-inifile。与这里的简单片段相比,这可能是过度杀伤...
#2
11
Use the InIFile Gem
As @method said, use the inifile gem. There is also an ini gem but I haven't used it.
正如@method所说,使用inifile gem。还有一个ini宝石,但我没有使用它。
I found the documentation here a slightly more helpful than the documentation here which is where the gem page links to.
我发现这里的文档比这里的文档更有帮助,这是gem页面链接到的地方。
There were not many examples so here is a bit of code to get you started:
没有太多的例子,所以这里有一些代码可以帮助你入门:
Example Setup
First, create a file /tmp/desktop.ini
with these contents:
首先,使用以下内容创建文件/tmp/desktop.ini:
[Desktop Entry]
Version=1.0
Type=Application
Name=Foo Viewer
Comment=The best viewer for Foo objects available!
TryExec=fooview
Exec=fooview %F
Icon=fooview
Make sure you have run gem install inifile
from the command line.
确保从命令行运行gem install inifile。
Example Code
Create a file like /tmp/ini-test.rb
with these contents:
使用以下内容创建/tmp/ini-test.rb之类的文件:
require 'inifile'
require 'pp'
# read an existing file
file = IniFile.load('/tmp/desktop.ini')
data = file["Desktop Entry"]
#output one property
puts "here is one property:"
puts data["Name"]
# pretty print object
puts "here is the loaded file:"
pp file
# create a new ini file object
new_file = IniFile.new
# set properties
new_file["Desktop Entry"] = {
"Type" => "Application",
"Name" => 'test',
"Exec" => 'command',
}
# pretty print object
puts "here is a object created with new:"
pp new_file
# set file path
new_file.filename = "/tmp/new_ini_file.ini"
# save file
new_file.write()
puts "the new object has been saved as a file to /tmp/new_ini_file.ini"
Example Results
Running that file with ruby /tmp/ini-test.rb
should yield something like:
使用ruby /tmp/ini-test.rb运行该文件应该会产生如下内容:
here is one property:
Foo Viewer
here is the loaded file:
{ this output hidden for brevity }
here is a object created with new:
#<IniFile:0x007feeec000770
@comment=";#",
@content=nil,
@default="global",
@encoding=nil,
@escape=true,
@filename=nil,
@ini=
{"Desktop Entry"=>
{"Type"=>"Application",
"Name"=>"test",
"Exec"=>"command",
"Icon"=>"icon_filename",
"Comment"=>"comment"}},
@param="=">
the new object has been saved as a file to /tmp/new_ini_file.ini
Modify as required suit your needs.
根据需要修改以满足您的需求。
#3
2
Here's the module for reading and writing of .ini-files with as less change to original file as possible (for files which read humans and machines):
这是用于读取和写入.ini文件的模块,尽可能少地更改原始文件(对于读取人和机器的文件):
class IniFileExc < RuntimeError
end
class IniNode def initialize(name, value=nil) @line_start = -1; @line_end = -1; @level = 0; @name = name; @value = value; @keys = {}; @keylist = []; @modified = false; @deleted = false; end attr_reader :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted attr_writer :level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted
class iniNode def initialize(name,value = nil)@line_start = -1; @line_end = -1; @level = 0; @name = name; @value = value; @keys = {}; @keylist = []; @modified = false; @deleted = false; end attr_reader:level,:line_start,:line_end,:name,:value,:keylist,:keys,:modified,:deleted attr_writer:level,:line_start,:line_end,:name,:value,:keylist,:keys, :改性,:删除
def to_str return @name.to_s + ' = ' + @value.to_s; end
def to_str return @ name.to_s +'='+ @ value.to_s;结束
def to_s return @value.to_s; end def to_i return @value.to_i end def to_f return @value.to_f; end
def to_s return @ value.to_s; end def to_i return @ value.to_i end def to_f return @ value.to_f;结束
def insert(key, nil); return @keys[key]; end
def insert(key,nil); return @keys [key];结束
def insert(key, value) return false if (@keys.has_key?(key)); node = nil; if (value && ((value.class == IniNode) || (value.class == IniSection))) node = value; else if (@level <= 0) node = IniSection.new(key); else node = IniNode.new(key, value) end end node.line_start = @line_end + 1 if (node.line_start < 0); node.level = @level + 1; @keys[key] = node; @keylist.push(key); return true; end
def insert(key,value)返回false if(@ keys.has_key?(key)); node = nil; if(value &&((value.class == IniNode)||(value.class == IniSection)))node = value; else if(@level <= 0)node = IniSection.new(key); else node = IniNode.new(key,value)end end node.line_start = @line_end + 1 if(node.line_start <0); node.level = @level + 1; @keys [key] = node; @ keylist.push(键);返回true;结束
def []=(key, value) rc = insert(key, value); @keys[key].value = value; @keys[key].modified = true; @modified = true; end
def [] =(键,值)rc = insert(键,值); @keys [key] .value = value; @keys [key] .modified = true; @modified = true;结束
def delete(key) return false if (! @keys.has_key?(key)); @keys[key].deleted = true; @modified = true; end end
def delete(key)如果返回false(!@ keys.has_key?(key)); @keys [key] .deleted = true; @modified = true;结束
class IniSection < IniNode def initialize(name) super(name); end
class IniSection
def to_str return ('[' + @name + ']'); end end
def to_str return('['+ @name +']');结束
class IniFile < IniNode
def initialize(path, load=true)
super(path);
@lines = [];
reload() if (load);
end
def reload begin input = File.new(@name, "r"); rescue raise; else prevnode = node = self; lineno = 0; input.each do |line| @lines.push(line); parsed_node = parse_line(lineno, line); if (parsed_node); if (parsed_node.class == IniSection) if (parsed_node != node) prev_node = node; node = parsed_node; insert(node.name, node); prev_node.line_end = lineno - 1; end else node.insert(parsed_node.name, parsed_node); end end lineno += 1; end input.close;
def reload begin input = File.new(@ name,“r”);救援;否则prevnode = node = self; lineno = 0; input.each do | line | @ lines.push(线); parsed_node = parse_line(lineno,line); if(parsed_node); if(parsed_node.class == IniSection)if(parsed_node!= node)prev_node = node; node = parsed_node; insert(node.name,node); prev_node.line_end = lineno - 1; end else node.insert(parsed_node.name,parsed_node); end end lineno + = 1;结束input.close;
node.line_end = @line_end = lineno - 1;
end
end
def parse_line(lineno, line) return nil if (line =~ /^\s*$/); return nil if (line =~ /^\s*#/); return nil if (line =~ /^\s*;/); if (line =~ /^\s*[\s*(.+)\s*].$/) rv = IniSection.new($1); rv.line_start = lineno; rv.level = @level + 1; return rv; elsif (line =~ /^\s(\S?.[^=\s])\s=\s*(\S?[^#;][^#;\s\n]).$/) rv = IniNode.new($1, $2); rv.line_start = rv.line_end = lineno; rv.level = @level + 2; return rv; end return nil; end
def parse_line(lineno,line)返回nil if(line =〜/ ^ \ s * $ /); return nil if(line =〜/ ^ \ s *#/); return nil if(line =〜/ ^ \ s *; /); if(line =〜/^\s* [\s*(.+)\s*].$/)rv = IniSection.new($ 1); rv.line_start = lineno; rv.level = @level + 1;返回rv; elsif(line =〜/^ \ s (\S?。[^ = \ ss])\s=\s*(\S?[^#;][^#;\s\n]).$/) rv = IniNode.new($ 1,$ 2); rv.line_start = rv.line_end = lineno; rv.level = @level + 2;返回rv;结束回报无;结束
def write inserted = {}; @keylist.each do |sect| sectnode = @keys[sect]; next if (!sectnode.modified || sectnode.deleted); if (sectnode.line_end < 0) @lines.push("\n"); @lines.push(sectnode.to_str + "\n"); end sectnode.keylist.each do |key| keynode = sectnode.keys[key]; next if (!keynode.modified || keynode.deleted); if (keynode.line_end < 0) if (sectnode.line_end < 0) @lines.push(keynode.to_str + "\n"); else idx = sectnode.line_end.to_i; inserted[idx] = [] if (! inserted.has_key?(idx)); inserted[idx].push(keynode.to_str); end else line = @lines[keynode.line_start]; if (line =~ /^(\s*)(\S?.[^=\s]\s=\s*\S?.+[^#;\s])(\s*[#;].)$/) line = $1 + keynode.to_str + $3 + "\n"; else line = line.gsub(/^(\s)(\S?.[^=\s]\s=\s*\S?[^#;]+[^#;\n\s])(.*)$/){ $1 + keynode.to_str + $3}; end @lines[keynode.line_start] = line; end end end
def write inserted = {}; @ keylist.each do | sect | sectnode = @keys [sect]; next if(!sectnode.modified || sectnode.deleted); if(sectnode.line_end <0)@ lines.push(“\ n”); @ lines.push(sectnode.to_str +“\ n”);结束sectnode.keylist.each do | key | keynode = sectnode.keys [key]; next if(!keynode.modified || keynode.deleted); if(keynode.line_end <0)if(sectnode.line_end <0)@ lines.push(keynode.to_str +“\ n”); else idx = sectnode.line_end.to_i; inserted [idx] = [] if(!inserted.has_key?(idx));插入[IDX] .push(keynode.to_str); end else line = @lines [keynode.line_start]; if(line =〜/^(\s*)(\??????????? 。)$ /)line = $ 1 + keynode.to_str + $ 3 +“\ n”; else line = line.gsub(/ ^(\ s)(\ S?。[^ = \ s] \ s = \ s * \ S?[^#;] + [^#; \ n \ s])( 。*)$ /){$ 1 + keynode.to_str + $ 3}; end @lines [keynode.line_start] = line;最终结束
deleted = {};
@keylist.each do |sect|
sectnode = @keys[sect];
next if (!sectnode.deleted && !sectnode.modified);
if (sectnode.deleted && (sectnode.line_start >= 0) && (sectnode.line_end >= 0) \
&& (sectnode.line_end >= sectnode.line_start))
for i in sectnode.line_start..sectnode.line_end
deleted[i] = true;
end
end
sectnode.keylist.each do |key|
keynode = sectnode.keys[key];
next if (!keynode.deleted);
deleted[keynode.line_start.to_i] = true \
if ((keynode.line_start >= 0) && (keynode.line_end >= 0) && (keynode.line_start == keynode.line_end));
end
end
begin
file = File.new(@name, 'w');
rescue
raise(IniFileExc, "Failed to open " + @name + " for writing: #{$!}", caller);
else
cnt = -1;
@lines.each do |line|
cnt += 1;
if (inserted.has_key?(cnt))
inserted[cnt].each do |ins|
file.puts(ins + "\n");
end
end
next if (deleted[cnt]);
file.puts(line);
end
file.close;
end
end end
Usage example:
begin
ini = IniFile.new('file.ini');
ini['common']['param'] = 'value';
ini['common'].delete('unused_param');
ini.delete('unused_section');
print "Valuable value: ", ini['common']['param'], "\n";
ini.write;
rescue IniFileExc
print "Oh, that's not good: ", $!, "\n";
end
Hope this helps.
希望这可以帮助。
#4
#5
0
If I understand correctly,
如果我理解正确,
outFile = File.new('out.ini', 'w')
File.open('in.ini', 'r') do |inFile|
inFile.each_line do |line|
# foo is the entry you want to change, baz is its new value.
outFile.puts(line.sub(/foo=(.*)/, 'foo=baz'))
end
end
outFile.close
Note that when you use File.open
with a block, the file will automatically be closed when the block terminates.
请注意,将File.open与块一起使用时,该块将在块终止时自动关闭。
#6
-4
file = File.new("your.ini", "r")
while (line = file.gets)
puts "#{line}" #additionally make changes
end
file.close