Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Ruby way to update file lines

Reply
Thread Tools

Ruby way to update file lines

 
 
Mark Probert
Guest
Posts: n/a
 
      08-19-2004
Hi.

I have a need to update a config file. It uses '#' as a line comment
marker. The config file looks like:

# file comment
#
name1:foo1:barther
name2:foo2:barther
name3:foo3:barther
name4:foo4:barther

The name:foo combination is unique.

What is the most efficient way to read in the file, update the line, and
then write it back to the file. One update would be to place a '#' in col
1

#name3:foo3:barther

Any thoughts appreciated.

-mark.
 
Reply With Quote
 
 
 
 
Kirk Haines
Guest
Posts: n/a
 
      08-19-2004
On Thu, 19 Aug 2004 10:45:54 +0900, Mark Probert wrote

>
> What is the most efficient way to read in the file, update the line,
> and then write it back to the file. One update would be to place a
> '#' in col 1
>
> #name3:foo3:barther
>
> Any thoughts appreciated.


Unless the file is very large, my initial thought is just to read the file
to an array. Edit, then rewrite the file.


Kirk Haines


 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      08-19-2004

"Mark Probert" <(E-Mail Removed)> schrieb im Newsbeitrag
news:Xns9549BE97C59B0probertmnospamacmorg@198.161. 157.145...
> Hi.
>
> I have a need to update a config file. It uses '#' as a line comment
> marker. The config file looks like:
>
> # file comment
> #
> name1:foo1:barther
> name2:foo2:barther
> name3:foo3:barther
> name4:foo4:barther
>
> The name:foo combination is unique.
>
> What is the most efficient way to read in the file, update the line, and
> then write it back to the file. One update would be to place a '#' in col
> 1
>
> #name3:foo3:barther
>
> Any thoughts appreciated.
>
> -mark.


Some code thoughts below

Regards

robert


# match keys
COMMENT = lambda {|key, val| "# #{key}:#{val}"}
DELETE = lambda { nil }

tasks = {
"foo:bar" => COMMENT,
"foo1:bar1" => DELETE,
}

conf = File.readlines("conf.txt")

# manipulate
conf.map! do |line|
if /^([^:]+:[^:]+).*)$/ =~ line && (fun = tasks[$1])
fun.call $1, $2
else
line
end
end

# remove deleted lines
conf.compact!

File.open("conf-1.txt", "w") {|io| io.puts conf }

#
# alternative -----------------------------------------
#

# use regexp as line matcher
tasks = {
/^foo1:bar1:/ => lambda {|line| "# #{line}"},
/^\s*#\s*foo.bar:/ => lambda {|line| line.sub(/^\s*#\s*/, '' )},
}


conf = File.readlines("conf-1.txt")

# manipulate
conf.map! do |line|
p,f = tasks.find {|patt, fun| patt =~ line}
f ? f.call( line ) : line
end

# remove deleted lines
conf.compact!

File.open("conf-2.txt", "w") {|io| io.puts conf }

 
Reply With Quote
 
Kristof Bastiaensen
Guest
Posts: n/a
 
      08-19-2004
On Thu, 19 Aug 2004 01:44:10 +0000, Mark Probert wrote:

> Hi.
>
> I have a need to update a config file. It uses '#' as a line comment
> marker. The config file looks like:
>
> # file comment
> #
> name1:foo1:barther
> name2:foo2:barther
> name3:foo3:barther
> name4:foo4:barther
>
> The name:foo combination is unique.
>
> What is the most efficient way to read in the file, update the line, and
> then write it back to the file. One update would be to place a '#' in col
> 1
>
> #name3:foo3:barther
>
> Any thoughts appreciated.
>
> -mark.


You could use inplace edit. This can make ruby work like awk.
For example:

ruby -aF: -ni.bak -e 'print "#" if $F[0] == "name3"' configfile

KB
 
Reply With Quote
 
Mark Probert
Guest
Posts: n/a
 
      08-21-2004
"Robert Klemme" <(E-Mail Removed)> wrote:

>
> Some code thoughts below
>
> Regards
>
> robert
>
>
> # match keys
> COMMENT = lambda {|key, val| "# #{key}:#{val}"}
> DELETE = lambda { nil }
>
> tasks = {
> "foo:bar" => COMMENT,
> "foo1:bar1" => DELETE,
> }
>
> conf = File.readlines("conf.txt")
>
> # manipulate
> conf.map! do |line|
> if /^([^:]+:[^:]+).*)$/ =~ line && (fun = tasks[$1])
> fun.call $1, $2
> else
> line
> end
> end
>
> # remove deleted lines
> conf.compact!
>
> File.open("conf-1.txt", "w") {|io| io.puts conf }
>


I liked this one Thanks.

One minor correction: COMMENT and DELETE should be lower case. Ruby 1.8
spits and error about constants otherwise.

-mark.
 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      08-21-2004

"Mark Probert" <(E-Mail Removed)> schrieb im Newsbeitrag
news:Xns954C7C2A261F8probertmnospamtelusn@198.161. 157.145...
> "Robert Klemme" <(E-Mail Removed)> wrote:
>
> >
> > Some code thoughts below
> >
> > Regards
> >
> > robert
> >
> >
> > # match keys
> > COMMENT = lambda {|key, val| "# #{key}:#{val}"}
> > DELETE = lambda { nil }
> >
> > tasks = {
> > "foo:bar" => COMMENT,
> > "foo1:bar1" => DELETE,
> > }
> >
> > conf = File.readlines("conf.txt")
> >
> > # manipulate
> > conf.map! do |line|
> > if /^([^:]+:[^:]+).*)$/ =~ line && (fun = tasks[$1])
> > fun.call $1, $2
> > else
> > line
> > end
> > end
> >
> > # remove deleted lines
> > conf.compact!
> >
> > File.open("conf-1.txt", "w") {|io| io.puts conf }
> >

>
> I liked this one Thanks.


Thanks, too!

> One minor correction: COMMENT and DELETE should be lower case. Ruby 1.8
> spits and error about constants otherwise.


They are meant to be constants because they *are* constant. I just put both
variants into a single file but you'll likely need only one of them, don't
you?

Regards

robert

 
Reply With Quote
 
Mark Probert
Guest
Posts: n/a
 
      08-21-2004
"Robert Klemme" <(E-Mail Removed)> wrote in
news:(E-Mail Removed):
>
> They are meant to be constants because they *are* constant. I just
> put both variants into a single file but you'll likely need only one
> of them, don't you?
>

When I leave them as constants, Ruby complains with the following error:

deln.rb:37: dynamic constant assignment
COMMENT = lambda {|key, val| "# #{key}:#{val}" }
^

In the end, it worked out well. My code snippet looks like:

# create a function map for the items we want to delete
comment = lambda {|key, val| "# #{key}:#{val}" }
delete = lambda {|key, val| nil }
checkmap = {}
@nodelist.each do |n|
key = "#{n.name}:#{n.ip}"
checkmap[key] = (@remove) ? delete : comment
end

Where I now have the option of making the deletion permanent or just
commenting it out. Which is perfect for my application.

Regards,

-mark.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      08-22-2004

"Mark Probert" <(E-Mail Removed)> schrieb im Newsbeitrag
news:Xns954CA02966DD9probertmnospamtelusn@198.80.5 5.250...
> "Robert Klemme" <(E-Mail Removed)> wrote in
> news:(E-Mail Removed):
> >
> > They are meant to be constants because they *are* constant. I just
> > put both variants into a single file but you'll likely need only one
> > of them, don't you?
> >

> When I leave them as constants, Ruby complains with the following error:
>
> deln.rb:37: dynamic constant assignment
> COMMENT = lambda {|key, val| "# #{key}:#{val}" }
> ^


Then you got the scoping wrong. Constants should be defined on top level or
class / module scope, otherwise they are of not much use: what do you gain
by reevaluationg and assigning an expression on each method invocation?
That's not what constants are intended for. You probably did something like
this:

>> def foo() FOO = "bar" end

SyntaxError: compile error
(irb):2: dynamic constant assignment
def foo() FOO = "bar" end
^
from (irb):2

While it should be

FOO = "bar"
def foo() ... end
# use FOO
or

class Any
FOO = "bar"
# use FOO
end

Both of them don't trigger warnings unless you do multiple assignments to
the same constant:

>> FOO = "bar"

=> "bar"
>> FOO = "bar"

(irb):2: warning: already initialized constant FOO
=> "bar"

> In the end, it worked out well. My code snippet looks like:
>
> # create a function map for the items we want to delete
> comment = lambda {|key, val| "# #{key}:#{val}" }
> delete = lambda {|key, val| nil }
> checkmap = {}
> @nodelist.each do |n|
> key = "#{n.name}:#{n.ip}"
> checkmap[key] = (@remove) ? delete : comment
> end
>
> Where I now have the option of making the deletion permanent or just
> commenting it out. Which is perfect for my application.


Fine.

robert

 
Reply With Quote
 
Mark Probert
Guest
Posts: n/a
 
      08-22-2004
"Robert Klemme" <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

>
> Then you got the scoping wrong.
>

You are correct. Thank you for the clarification.

-mark.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
one interview question, 17 lines in java, 3 lines in ruby. WuyaSea Operator Java 48 09-24-2007 01:50 AM
Re: one interview question, 17 lines in java, 3 lines in ruby. Lew Java 0 09-20-2007 12:34 AM
To delete few lines and add few lines at the end of a text file using c program Murali C++ 2 03-09-2006 04:45 PM
Asp.Net Calender, how to display 5 lines if there are only 5 lines in one month? Jack ASP .Net 9 10-12-2005 03:44 AM
Re: how to read 10 lines from a 200 lines file and write to a new file?? Joe Wright C Programming 0 07-27-2003 08:50 PM



Advertisments