How to run this ruby file that needs an argument? - ruby

I just wanted this function to run and get the output, but I can't seem to make it run.
I installed Interactive Ruby for this.
This is the code:
class Float
def to_sn # to scientific notation
"%E" % self
end
def self.from_sn str # generate a float from scientific notation
("%f" % str).to_f
end
end
# Pass in filename as only argument
if ARGV.size != 1
puts "Usage: ./converSTL.rb [stl filename]"
exit
end
begin
original = File.new(ARGV[0], "r")
# Read first line - check binary or ASCII
tempLine = original.gets
if tempLine.include? "solid"
outFilename = ARGV[0].sub(/\.stl/i, '-binary.stl')
puts "#{ARGV[0]} is in ASCII format, converting to BINARY: #{outFilename}"
outFile = File.new(outFilename, "w")
outFile.write("\0" * 80) # 80 bit header - ignored
outFile.write("FFFF") # 4 bit integer # of triangles - filled later
triCount = 0
while temp = original.gets
next if temp =~ /^\s*$/ or temp.include? 'endsolid' # ignore whitespace
temp.sub! /facet normal/, ''
normal = temp.split(' ').map{ |num| Float.from_sn num }
triCount += 1
temp = original.gets # 'outer loop'
temp = original.gets
vertexA = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets
vertexB = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets
vertexC = temp.sub(/vertex/, '').split(' ').map{ |num| Float.from_sn num }
temp = original.gets # 'endsolid'
temp = original.gets # 'endfacet'
outFile.write(normal.pack("FFF"))
outFile.write(vertexA.pack("FFF"))
outFile.write(vertexB.pack("FFF"))
outFile.write(vertexC.pack("FFF"))
outFile.write("\0\0")
end
outFile.seek(80, IO::SEEK_SET)
outFile.write([ triCount ].pack("V"))
outFile.close
else
outFilename = ARGV[0].sub(/\.stl/i, '-ascii.stl')
puts "#{ARGV[0]} is in BINARY format, converting to ASCII: #{outFilename}"
outFile = File.new(outFilename, "w")
outFile.write("solid \n")
original.seek(80, IO::SEEK_SET)
triCount = original.read(4).unpack('V')[0]
triCount.times do |triNdx|
normal = original.read(12).unpack('FFF')
vertexA = original.read(12).unpack('FFF')
vertexB = original.read(12).unpack('FFF')
vertexC = original.read(12).unpack('FFF')
original.seek(2, IO::SEEK_CUR)
outFile.write(" facet normal #{normal[0].to_sn} #{normal[1].to_sn} #{normal[2].to_sn}\n")
outFile.write(" outer loop\n")
outFile.write(" vertex #{vertexA[0].to_sn} #{vertexA[1].to_sn} #{vertexA[2].to_sn}\n")
outFile.write(" vertex #{vertexB[0].to_sn} #{vertexB[1].to_sn} #{vertexB[2].to_sn}\n")
outFile.write(" vertex #{vertexC[0].to_sn} #{vertexC[1].to_sn} #{vertexC[2].to_sn}\n")
outFile.write(" endloop\n")
outFile.write(" endfacet\n")
end
outFile.write("endsolid \n")
outFile.close
end
original.close
rescue => error
puts "Error: #{error}"
end
And everytime I try to run it, I get this error:

It's a script that can be run from cmd with
ruby convertST1.rb file.stl

Related

How to Hash content to write in file as format mentioned as below?

I have wrote my ruby script for that. In that you can check "all_data" has all required content.
#!/usr/bin/env ruby
require 'docx'
file_data = []
name_file = "test"
t = ""
array_desc = []
heading_hash = {}
all_data = {}
temp = ""
output = ""
folder_name = ""
directory_name = ""
flag = true
count = 0
md_file_name = ''
Dir.glob("**/*.docx") do |file_name|
doc = Docx::Document.open(file_name)
first_table = doc.tables[0]
doc.tables.each do |table|
table.rows.each do |row| # Row-based iteration
row.cells.each_with_index do |cell, i|
if i == 2
file_data << cell.text.gsub('=','')
end
end
end
end
file_data.each_with_index do |l, d|
if l.include? file_data[d]
if ((l.strip)[0].to_i != 0)
md_file_name = file_data[d].split(".")
#start folder name
if flag
directory_name = md_file_name[0].to_i
flag = false
end
count +=1
t = file_data[d+1]
if(array_desc.size > 0)
heading_hash[temp] = array_desc
all_data[md_file_name[0].strip] = heading_hash
array_desc = []
end
else
if(t != l)
array_desc << l
temp = t
end
end
end
end
if(array_desc.size> 0)
heading_hash[temp] = array_desc
all_data[md_file_name[0].strip] = heading_hash
array_desc = []
end
all_data.each do |k, v|
v.each do |(hk, hv)|
if hk != ""
chapter_no = k
if (k[0,1] == 0.to_s)
chapter_no = k
else
chapter_no = "0#{k}"
end
Dir.mkdir("#{chapter_no}") unless File.exists?("#{chapter_no}")
output_name = "#{chapter_no}/#{File.basename("01", '.*')}.md"
output = File.open(output_name, 'w')
# output << "#"+"#{hk}\n\n"
# output << "#{hv} \n\n"
hv.each do |des|
# puts des
end
end
end
end
end
source docx file
download above file and put sctip and docx (source file) in same folder. When you will run script form terminal ($./script.rb) you will see folder name as 01,02.....etc. And inside there will be file with md extension.
I want to output as below description:
## FOLDER 01 > FILE 01.md, here data in file like hk as heading (for Heading you can put # before hk)and hv
## FOLDER 02 > FILE 01.md, here data in file like hk as heading (for Heading you can put # before hk)and hv
Please use my code and check that is working or not.
Dir.glob("**/*.docx") do |file_name|
doc = Docx::Document.open(file_name)
first_table = doc.tables[0]
doc.tables.each do |table|
table.rows.each do |row|
row.cells.each_with_index do |cell, i|
if i == 2
file_data << cell.text.gsub('=','')
end
end
end
end
file_data.each_with_index do |l, d|
if ((l.strip)[0].to_i != 0)
md_file_name = file_data[d].split(".")
#start folder name
if flag
directory_name = md_file_name[0].to_i
flag = false
end
count +=1
t = file_data[d+1]
if(array_desc.size > 0)
heading_hash[temp] = array_desc
array_desc=[]
all_data[file_data[d+1]] = array_desc
end
else
if(t != l)
array_desc << l
temp = t
end
end
end
chapter_no = 1
all_data.each do |k, v|
Dir.mkdir("#{chapter_no}") unless File.exists?("#{chapter_no}")
output_name = "#{chapter_no}/#{File.basename("01", '.*')}.md"
output = File.open(output_name, 'a')
output << "#"+"#{k}\n\n"
v.each do |d|
output << "#{d} \n"
end
chapter_no= chapter_no+1
end
end
It will give exact output as you shared above. Let me know if you need more help.

how i could wrapped two command in ruby?

Im trying to wrapped this two command in ruby but not work
ruby -a -ne 'print $F[0].gsub(/=(.*?)&/," \"\\1\" and ")' prueban > prueban2
ruby -a -F';' -ne 'puts $F[0].sub("less"," <")' prueban2 > prueban3
this is my command
File.open("text.txt", "r") do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
fx= puts parts[0].gsub(/=(.*?)&/," \"\\1\" and ")
end
fx.readlines.each do |line|
parts = line.chomp.split(';')
fx= puts parts[0].gsub("less"," <")
end
end
this is my file
pricegreater=2&priceless=4&seleccionequal=pet&
and this is my expected output
pricegreater "2" and price < "4" and seleccionequal "pet" and
I dont know whats is doing wrong please help me
Here's a reworked version of the core function to show how to do it in a more Ruby-esque way:
# Define a lookup table of all substitutions
REWRITE = {
'greater' => '>',
'less' => '<',
'equal' => '='
}
# Use the lookup table to create a regular expression that matches them all
REWRITE_RX = Regexp.new(Regexp.union(REWRITE.keys).to_s + '\z')
def rewrite(input)
# Split up each main part of the input on &
input.split('&').map do |pair|
# Carve up each part into a var and value on =
var, value = pair.split('=')
# Replace terms found in the lookup table
var.sub!(REWRITE_RX) do |m|
' ' + REWRITE[m]
end
# Combine these to get the result
[ var, value ].join(' ')
end.join(' and ')
end
Put into action you get this:
rewrite("pricegreater=2&priceless=4&seleccionequal=pet&")
# => "price > 2 and price < 4 and seleccion = pet"
I solved with this
File.open("text.txt", "r") do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
f = File.open('text2.txt', 'w')
old_out = $stdout
$stdout = f
puts parts[0].gsub(/=(.*?)&/," \"\\1\" and ")
f.close
$stdout = old_out
end
end
File.open("text2.txt", "r") do |fi|
fi.readlines.each do |line|
parts = line.chomp.split(';')
f = File.open('text3.txt', 'w')
old_out = $stdout
$stdout = f
puts parts[0].sub("less"," <")
f.close
$stdout = old_out
end
end

Ruby noobster does not understand arrays

I'm not a programmer, but I want to become one. So, I read books, I do tutorials and I ask questions. Here is the question:
I'm trying to do a Ruby quiz – the one with the Solitaire cypher (http://rubyquiz.com/quiz1.html). I wrote some code that works pretty well, except that at one point it alters the key_deck array which should be a reference to the end of the program. I do not know where this happens or why.
Here is my noobish code:
$characters = Array ('A' .. 'Z')
def encode to_encode, input_deck
trekljdfg = input_deck
edeck = input_deck
work_string = ''
to_encode.upcase.split("").each do |char|
if $characters.include?(char)
work_string.concat(char)
end
end
work_string = work_string + ('X' * ((5 - (work_string.length % 5)) % 5))
keystream_string = ''
while keystream_string.length < work_string.length do # <-- generate keystream
edeck = permutation(edeck)
keystream_string.concat(get_letter(edeck))
end
encoded = combine_with_keystream(work_string, keystream_string)
encoded = split_string_in_groups(encoded)
return encoded
end
def decode to_decode, input_deck
ddeck = input_deck
to_decode = to_decode.delete(' ')
keystream_string = ''
while keystream_string.length < to_decode.length do # <-- generate keystream
ddeck = permutation(ddeck)
keystream_string.concat(get_letter(ddeck))
end
array_to_decode = text_to_numbers to_decode
array_keystream_string = text_to_numbers keystream_string
decoded = ''
for i in 0..(array_to_decode.length-1)
if array_to_decode[i] >= array_keystream_string[i]
decoded.concat($characters[(array_to_decode[i] - array_keystream_string[i])-1])
else
decoded.concat($characters[(array_to_decode[i] + 26 - array_keystream_string[i])-1])
end
end
decoded = split_string_in_groups decoded
return decoded
end
def permutation deck_to_change
deck = deck_to_change
def swap array, joker
work_array = array
joker_position = work_array.index(joker)
if joker_position == (work_array.length-1)
temp_array = work_array.slice!(1..(work_array.length-2))
work_array = work_array + temp_array
else
work_array[joker_position], work_array[joker_position+1] = work_array[joker_position+1], work_array[joker_position]
end
return work_array
end
deck = swap(deck, 'A') # <-- swap first joker
2.times do # <-- swap second joker
deck = swap(deck, 'B')
end
if deck.index('A') < deck.index('B') # <-- triple cut
joker_position1 = deck.index('A')
joker_position2 = deck.index('B') - joker_position1
else
joker_position1 = deck.index('B')
joker_position2 = deck.index('A') - joker_position1
end
if joker_position1 == 0
temp_array1 = []
else
temp_array1 = deck.slice!(0..joker_position1-1)
end
if joker_position2 == deck.length-1
temp_array2 = []
else
temp_array2 = deck.slice!(joker_position2+1..deck.length-1)
end
deck = temp_array2 + deck + temp_array1
if (deck.last != 'A') | (deck.last != 'B') # <-- count cut
temp_array1 = deck.slice!(0..deck.last.to_i-1)
temp_array2 = deck.pop(1)
deck = deck + temp_array1 + temp_array2
end
return deck
end
def get_letter deck
first = deck.first
case first
when 'A'
first = '53'
when 'B'
first = '53'
end
if (deck[first.to_i] == 'A') | (deck[first.to_i] == 'B')
return ''
else
return $characters[((deck[first.to_i]).to_i-1) % 26]
end
end
def text_to_numbers text
array = []
text.upcase.split("").each do |char|
array.push($characters.index(char)+1)
end
return array
end
def combine_with_keystream string1, string2
temp_array1 = text_to_numbers string1
temp_array2 = text_to_numbers string2
string = ''
for i in 0..(temp_array1.length-1)
tmp = temp_array1[i] + temp_array2[i]
if tmp > 26
tmp = tmp - 26
end
string.concat($characters[tmp-1])
end
return string
end
def split_string_in_groups string
return string.scan(/.{1,5}/).join(" ")
end
#-begin-------------------------
key_deck = ('1' .. '52').to_a + ['A', 'B'] # <-- this is the key deck ^^
string_to_encode = 'Code in Ruby live longer!' # <-- this is the string to be encoded
string_to_decode = 'GLNCQ MJAFF FVOMB JIYCB' # <-- this is the string to be decoded
puts "Your encoded text is: #{encode(string_to_encode, key_deck)}"
puts "Your decoded text is: #{decode(string_to_decode, key_deck)}"
You are using slice! to find your deck's permutations, which changes the input array.
The easiest solution is to dup the array before working on it:
def encode to_encode, input_deck
trekljdfg = input_deck.dup
edeck = input_deck.dup
# ..
end
def decode to_decode, input_deck
ddeck = input_deck.dup
# ..
end
dup creates a copy of the array, which you can safely mutilate.
Your permutation function alters the deck. You pass it a reference to the original deck, so any changes you do on the reference will actually change the original. Try something like this instead:
key_deck = [....]
...
puts "#{encode(string_to_encode, key_dec.clone}"
The clone method will make a new copy of the array for you so all changes will only apply to the copy.
Or you can just avoit the entire problem by using the Array#shuffle method:
puts "#{encode(string_to_encode, key_dec.shuffle}"
That will give an already shuffled deck to the encode function.

How to write code ruby to collect data while run loop condition

I am quit new in ruby and I need your help.
Now I want to write ruby code to collect some data while looping.
I have 2 code for this work.
My objective is collect sum score from text that split from input file.
-first, run test_dialog.rb
-Second, change input file for this format
from
AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700 enquire-privilege_card
to
AA 0.88
BB 0.82
CC 0.77
-Then use each text that separate check on dialog condition. If this data appear in dialog ,store point until end of text (AA --> BB --> CC)
-Finally get average score.
I have problem will separating and use loop for collect point in same time.
Please help.
Best regard.
PS.
score will return if match with dialog
score of input line 1 should be (0.88+0.82+0.77/3) [match condition 1].
if no match, no score return.
Input data
AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700 enquire-privilege_card
BB:0.88:320:800|EE:0.82:1040:1330|FF:0.77:1330:1700 enquire-privilege_card
EE:0.88:320:800|QQ:0.82:1040:1330|AA:0.77:1330:1700|RR:0.77:1330:1700|TT:0.77:1330:1700 enquire-privilege_card
test_dialog.rb
#!/usr/bin/env ruby
# encoding: UTF-8
#
# Input file:
# hyp(with confidence score), ref_tag
#
# Output:
# hyp, ref_tag, hyp_tag, result
#
require_relative 'dialog'
require_relative 'version'
unless ARGV.length > 0
puts 'Usage: ruby test_dialog.rb FILENAME [FILENAME2...]'
exit(1)
end
counter = Hash.new{|h,k| h[k]=Hash.new{|h2,k2| h2[k2]=Hash.new{|h3,k3| h3[k3]=0}}}
thresholds = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
puts %w(hyp ref_tag hyp_tag result).join("\t")
ARGV.each do |fname|
open(fname, 'r:UTF-8').each do |line|
hyp, ref_tag = line.strip.split(/\t/)
key = if ref_tag == "(reject)"
:reject
else
:accept
end
counter[fname][key][:all] += 1
thresholds.each do |threshold|
hyp_all = get_response_text(hyp, threshold)
hyp_tag = if hyp_all==:reject
"(reject)"
else
hyp_all.split(/,/)[1]
end
result = ref_tag==hyp_tag
counter[fname][key][threshold] += 1 if result
puts [hyp.split('|').map{|t| t.split(':')[0]}.join(' '),
ref_tag, hyp_tag, result].join("\t") if threshold==0.0
end
end
end
STDERR.puts ["Filename", "Result"].concat(thresholds).join("\t")
counter.each do |fname, c|
ca_all = c[:accept].delete(:all)
cr_all = c[:reject].delete(:all)
ca = thresholds.map{|t| c[:accept][t]}.map{|n| ca_all==0 ? "N/A" : '%4.1f' % (n.to_f/ca_all*100) }
cr = thresholds.map{|t| c[:reject][t]}.map{|n| cr_all==0 ? "N/A" : '%4.1f' % (n.to_f/cr_all*100) }
STDERR.puts [fname, "Correct Accept"].concat(ca).join("\t")
STDERR.puts [fname, "Correct Reject"].concat(cr).join("\t")
end
dialog.rb
# -*- coding: utf-8 -*-
#
# text : AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700|DD:0.71:1700:2010|EE:1.00:2070:2390|FF:0.56:320:800|GG:0.12:1330:1700
#
def get_response_text text, threshold, dsr_session_id=nil
# ...
#p "result text >> " + text
# Promotion => detail => rate
# Promotion IR/IDD => high priority than enquire-promotion
# Rate IR/IDD => high priority than enquire-rate
# Problem IR/IDD => high priority than enquire-service_problem
# Internet IR/IDD => high priority than enquire-internet
# Cancel Net => enquire-internet NOT cancel-service
# Lost-Stolen => +Broken
memu = ""
intent = ""
prompt = ""
intent_th = ""
intent_id = ""
# strInput = text.gsub(/\s/,'')
strInput = text.split('|').map{|t| t.split(':')[0]}.join('')
puts ("****strINPUT*****")
puts strInput
scores = text.split('|').map{|t| t.split(':')[1].to_f}
puts ("****SCORE*****")
puts scores
avg_score = scores.inject(0){|a,x| a+=x} / scores.size
puts ("****AVG-Score*****")
puts avg_score
if avg_score < threshold
return :reject
end
# List of Country
country_fname = File.dirname(__FILE__)+"/country_list.txt"
country_list = open(country_fname, "r:UTF-8").readlines.map{|line| line.chomp}
contry_reg = Regexp.union(country_list)
# List of Mobile Type
mobile_fname = File.dirname(__FILE__)+"/mobile_list.txt"
mobile_list = open(mobile_fname, "r:UTF-8").readlines.map{|line| line.chomp}
mobile_reg = Regexp.union(mobile_list)
# List of Carrier
carrier_fname = File.dirname(__FILE__)+"/carrier_list.txt"
carrier_list = open(carrier_fname, "r:UTF-8").readlines.map{|line| line.chomp}
carrier_reg = Regexp.union(carrier_list)
if (strInput =~ /AA|BB/ and strInput =~ /CC/)
intent = "enquire-payment_method"
elsif (strInput =~ /EE/) and ("#{$'}" =~ /QQ|RR/)
intent = "enquire-balance_amount"
elsif (strInput =~ /AA|EE/i) and (strInput =~ /TT/i)
intent = "enquire-balance_unit"
elsif (strInput =~ /DD|BB|/i) and (strInput =~ /FF|AA/i)
intent = "service-balance_amount"
end
Parse as follows:
str = 'AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700 enquire-privilege_card'
str.split( /[:|]/ ).select.with_index {| code, i | i % 4 < 2 ; }.join( ' ' )
# => "AA 0.88 BB 0.82 CC 0.77"

How to read an INI file in ruby

How do I read/write an ini file in ruby. I have an ini file that I need to
read
change an entry
write out to a different location
How would I do that in ruby? The documentation on this is bleak.
Use the InIFile Gem
As #method said, use the inifile gem. There is also an ini gem but I haven't used it.
I found the documentation here a slightly more helpful than the documentation here which is where the gem page links to.
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:
[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.
Example Code
Create a file like /tmp/ini-test.rb with these contents:
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:
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.
I recently used ruby-inifile. Maybe it's overkill compared to the simple snippets here...
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):
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
def to_str
return #name.to_s + ' = ' + #value.to_s;
end
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
insert(key, nil);
return #keys[key];
end
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 []=(key, value)
rc = insert(key, value);
#keys[key].value = value;
#keys[key].modified = true;
#modified = true;
end
def delete(key)
return false if (! #keys.has_key?(key));
#keys[key].deleted = true;
#modified = true;
end
end
class IniSection < IniNode
def initialize(name)
super(name);
end
def to_str
return ('[' + #name + ']');
end
end
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;
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 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
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.
Here's another option:
http://rubygems.org/gems/ini
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 = File.new("your.ini", "r")
while (line = file.gets)
puts "#{line}" #additionally make changes
end
file.close

Resources