Как прочитать INI-файл в ruby - PullRequest
7 голосов
/ 03 марта 2009

Как мне прочитать / записать INI-файл в ruby. У меня есть INI-файл, который мне нужен

  1. прочитать
  2. изменить запись
  3. выписать в другое место

Как бы я сделал это в ruby? Документация на это мрачная.

Ответы [ 6 ]

12 голосов
/ 29 марта 2014

Используйте InIFile Gem

Как сказал @method, используйте гем inifile . Существует также драгоценный камень ini , но я им не пользовался.

Я нашел документацию здесь немного более полезной, чем документация здесь , на которую ссылается страница гема.

Примеров было не так много, поэтому вот небольшой код, с которого можно начать:

Пример настройки

Сначала создайте файл /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

Убедитесь, что вы запустили gem install inifile из командной строки.

Пример кода

Создайте файл наподобие /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"

Пример результатов

Запуск этого файла с 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

Изменить в соответствии с вашими потребностями.

11 голосов
/ 04 марта 2009

Я недавно использовал ruby-inifile . Может быть, это излишне по сравнению с простыми фрагментами здесь ...

2 голосов
/ 25 сентября 2009

Вот модуль для чтения и записи .ini-файлов с как можно меньшим изменением исходного файла (для файлов, которые читают люди и машины):

class IniFileExc < RuntimeError end</p> <p>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</p> <p>def to_str return @name.to_s + ' = ' + @value.to_s; end</p> <p>def to_s return @value.to_s; end def to_i return @value.to_i end def to_f return @value.to_f; end</p> <p>def insert(key, nil); return @keys[key]; end</p> <p>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</p> <p>def []=(key, value) rc = insert(key, value); @keys[key].value = value; @keys[key].modified = true; @modified = true; end</p> <p>def delete(key) return false if (! @keys.has_key?(key)); @keys[key].deleted = true; @modified = true; end end</p> <p>class IniSection < IniNode def initialize(name) super(name); end</p> <p>def to_str return ('[' + @name + ']'); end end

<pre> class IniFile < IniNode def initialize(path, load=true) super(path); @lines = []; reload() if (load); end</p> <p>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;</p> <pre><code> node.line_end = @line_end = lineno - 1; end

конец

def parse_line (бельё, строка) вернуть nil if (line = ~ / ^ \ s * $ /); вернуть nil if (line = ~ / ^ \ s * # /); вернуть nil if (line = ~ / ^ \ s *; /); if (line = ~ /^\s*[\s*(.+)\s*].$/) rv = IniSection.new ($ 1); rv.line_start = белья; rv.level = @level + 1; возврат рв; элсиф #; \ s \ п]) $ /). rv = IniNode.new ($ 1, $ 2); rv.line_start = rv.line_end = lineno; rv.level = @level + 2; возврат рв; конец вернуть ноль; конец

def write вставлено = {}; @ keylist.each do | sect | sectnode = @keys [sect]; далее if (! sectnode.modified || sectnode.deleted); if (sectnode.line_end <0) @ Lines.push ( "\ п"); @ lines.push (sectnode.to_str + "\ n"); конец sectnode.keylist.each do | key | keynode = sectnode.keys [ключ]; далее if (! keynode.modified || keynode.deleted); if (keynode.line_end <0) if (sectnode.line_end <0) @ lines.push (keynode.to_str + "\ n"); еще idx = sectnode.line_end.to_i; вставлено [idx] = [] if (! insert.has_key? (idx)); вставляется [IDX] .С (keynode.to_str); конец еще line = @lines [keynode.line_start]; if (строка = ~ / ^ (\ s *) (\ S?. <em>[^ = \ s] \ s = \ s * \ S?. + [^ #; \ s]) (\ с * [#;]. ) $ /) строка = $ 1 + keynode.to_str + $ 3 + "\ n"; еще line = line.gsub (/ ^ (\ s ) (\ S?. [^ = \ s] \ s = \ s * \ S? [^ #;] + [^ # ; \ п \ s]) (*) $ /) {. $ 1 + keynode.to_str + $ 3}; конец @lines [keynode.line_start] = line; конец конец конец

<pre> 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</p> <pre><code>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

конец конец

Пример использования:


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

Надеюсь, это поможет.

1 голос
/ 08 сентября 2010

Вот еще один вариант: http://rubygems.org/gems/ini

0 голосов
/ 03 марта 2009

Если я правильно понимаю,

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

Обратите внимание, что при использовании File.open с блоком файл автоматически закрывается после завершения блока.

0 голосов
/ 03 марта 2009
file = File.new("your.ini", "r")
  while (line = file.gets)
   puts "#{line}" #additionally make changes
  end
file.close
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...