Functional Ruby equiv to this perl snippet

parses a text file looking for server names and ignoring lines

with start with the pound/hash sign.

sub load_server_list {
$filename = “serverlist.txt”;
open (SERVERLIST, $filename) or die “Can’t open $filename:$!”;

$i = 0;
       while (defined ($servername = <SERVERLIST>)) {
     if ($servername ne "\n") {
	if (substr($servername,0,1) ne "#") {
              chomp ($servername);
              $servers[$i] = "$servername";
	  $i = $i + 1;
	}
     }
    }
close (SERVERLIST);
$server_count = $i;

}

I am trying to convert a perl script I like to Ruby and I am not very
good at either!

Thanks!

Bob

Bob said:

parses a text file looking for server names and ignoring lines

with start with the pound/hash sign.

sub load_server_list {
$filename = “serverlist.txt”;
open (SERVERLIST, $filename) or die “Can’t open $filename:$!”;

$i = 0;
while (defined ($servername = )) {
if ($servername ne “\n”) {
if (substr($servername,0,1) ne “#”) {
chomp ($servername);
$servers[$i] = “$servername”;
$i = $i + 1;
}
}
}
close (SERVERLIST);
$server_count = $i;
}

Something like this:

def load_server_list(filename)
server_list =
File.open(filename,“r”) { |file|
while file.gets
next if ~ /^#/
~ /^(.*)$/
server_list << $1.chomp
end
}
return server_list
end

should work, but I didn’t try it. =)

bobx@linuxmail.org (Bob) writes:

parses a text file looking for server names and ignoring lines

with start with the pound/hash sign.

It’s pretty bad Perl, so here it is translated into pretty bad Ruby…

def load_server_list
filename = “serverlist.txt”
file = open(filename, “r”)
servers =
while line = file.gets
line.chop!
next unless line =~ /\S/
next if line =~ /^#/
servers << line
end
file.close
return servers
end

···


EFNet is like one big advertisement for lobotomies.

# parses a text file looking for server names and ignoring lines
# with start with the pound/hash sign.

and ignoring empty lines, no ?

I am trying to convert a perl script I like to Ruby and I am not very
good at either!

Something like this, it return an array

   def load_server_list(filename)
      servers =
      IO.foreach(filename) do |line|
         next if line[0] == ?# || line[0] == ?\n
         servers << line.chomp
      end
      servers
   rescue
      raise "Can't open #{filename} : #$!"
   end

to use it

  servers = load_server_list("serverlist.txt")

servers.size will give the same than $server_count

Guy Decoux

def load_server_list
$server_count = 0
$servers = []
File.open(‘serverlist.txt’).each do |line|
next if line =~ /^$/
next if line =~ /^#.$/
$servers << line.chomp.sub(/\s+#.
$/, ‘’)
$server_count += 1
end
end

load_server_list
p $server_count
p $servers

This has the added ability to remove comments after server names. My
sample serverlist.txt contained the following:

server1
#server2
server3

#server4
server5
server6 # comment after

An alternative implementation that doesn’t use global variables is as
follows:

def load_server_list
server_count = 0
servers = []
File.open(‘serverlist.txt’).each do |line|
next if line =~ /^$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
server_count += 1
end
[server_count, servers]
end

(server_count, servers) = load_server_list
p server_count, servers

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.10.21 at 13.12.15

Here is what I did…with your help and looking through different ways to
handle stuff.

get the servers out of the file

def load_server_list
servers = []
filename = 'serverlist.txt’
if FileTest.exist?(filename)
File.open(filename).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
else
puts "The serverlist.txt file does not exist."
exit
end
end

This tests for the existence of the file first and then the “else” clause
kicks in if it does not. Simple for me and that is what I need. : )

Thank you very much for your help! Sometimes one just needs a wall to bounce
thoughts off of instead of pounding the head into. : )

Bob

I realised that my first test wasn’t good for non-empty but blank
lines. The following fixes that. Also note that I’ve removed
server_count – you don’t need a separate count because servers.size
contains that information.

def load_server_list
servers = []
File.open(‘serverlist.txt’).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
end

servers = load_server_list
p servers.size, servers

– Austin Ziegler, austin@halostatue.ca on 2002.10.21 at 13.42.27

Here’s my attempt to squish that code down even further.

Simon Cozens simon@ermine.ox.ac.uk writes:

bobx@linuxmail.org (Bob) writes:

parses a text file looking for server names and ignoring lines

with start with the pound/hash sign.

It’s pretty bad Perl, so here it is translated into pretty bad Ruby…

def load_server_list
filename = “serverlist.txt”
file = open(filename, “r”)
servers =
while line = file.gets
line.chop!
next unless line =~ /\S/
next if line =~ /^#/
servers << line
end
file.close
return servers
end

def load_server_list(file_name)
servers =
IO.readlines(file_name).each { | line |
# Next line assumes input always has newlines
line = line.chomp!.strip # chomp instead of chop
next if line.empty? || line[0] == ?# # Use ?# just to be different
servers << line
}
return servers
end

servers = load_server_list(ARGV[0] || “serverlist.txt”)
server_count = servers.length

Jim

···


Jim Menard, jimm@io.com, http://www.io.com/~jimm/
“I invented the term Object-Oriented, and I can tell you I did not have C++
in mind.” – Alan Kay

“ts” decoux@moulon.inra.fr wrote in message
news:200210211713.g9LHDAI26610@moulon.inra.fr

parses a text file looking for server names and ignoring lines

with start with the pound/hash sign.

and ignoring empty lines, no ?
Yes! : )

Hi –

Here is what I did…with your help and looking through different ways to
handle stuff.

get the servers out of the file

def load_server_list
servers =
filename = ‘serverlist.txt’
if FileTest.exist?(filename)
File.open(filename).each do |line|

Just to point out that you’re introducing a wee race condition,
because it’s possible for the file to be deleted (by another process)
between the exist? test and the open. This may not be a practical
consideration in this case, but it’s probably not a good construct to
use in general.

  next unless line =~ /^\S+$/

That’s going to reject every line that has whitespace in it (not
counting the final \n); for example, both of these lines will be
rejected:

some_server_name # this line will be rejected
another_server_name

  next if line =~ /^#.*$/

The .*$ part is superfluous – it will always match if ^# matches :slight_smile:

Here’s a version that (I think) rejects comment lines and blank lines,
strips trailing comments, and returns the first non-space-containing
string it finds on a line. (You can wrap it in filetests if you wish
:slight_smile:

def load_server_list
filename = ‘serverlist.txt’
File.open(filename).map do |line|
Regexp.last_match[1] if /^\s*([^#\s]+)/.match(line)
end .compact
end

On the exception vs. filetest matter: remember that to handle an
exception you don’t have to write it into the method. For example,
when you call the method you can do:

begin
load_server_list
rescue => e
puts “Something went wrong: #{e}”
end

(I mention this because I think you said something before about not
wanting to write an exception handler directly in the method
definition.)

David

···

On Tue, 22 Oct 2002, Bob X wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

“Austin Ziegler” austin@halostatue.ca wrote in message
news:20021021174531.ZWLH5548.tomts9-srv.bellnexxia.net@hogwarts…

contains that information.

def load_server_list
servers =
File.open(‘serverlist.txt’).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
end

servers = load_server_list
p servers.size, servers
Cool…but what if serverlist.txt does not exist? The one thing I do like
about Perl is the “open file or die” test. I believe that I am “stuck” with
a rescue clause which is sometimes confusing for me (a newbie) to use when
it is located within a “def”.

Bob

dblack@candle.superlink.net writes:

if FileTest.exist?(filename)
File.open(filename).each do |line|

Just to point out that you’re introducing a wee race condition,
because it’s possible for the file to be deleted (by another process)
between the exist? test and the open.

Also, don’t forget that there are more ways an open can fail than just
ENOENT; but maybe in those conditions you’d prefer to throw an exception
anyway.

···


Old Japanese proverb:
There are two kinds of fools – those who never climb Mt. Fuji,
and those who climb it twice.

dblack@candle.superlink.net wrote in message
news:Pine.LNX.4.44.0210212217300.26314-100000@candle.superlink.net

Hi –

Here is what I did…with your help and looking through different ways
to
handle stuff.

get the servers out of the file

def load_server_list
servers =
filename = ‘serverlist.txt’
if FileTest.exist?(filename)
File.open(filename).each do |line|

Just to point out that you’re introducing a wee race condition,
because it’s possible for the file to be deleted (by another process)
between the exist? test and the open. This may not be a practical
consideration in this case, but it’s probably not a good construct to
use in general.
I had not thought of that actually. I will be the user of the script but I
guess you never know where they actually can go.

Bob

···

On Tue, 22 Oct 2002, Bob X wrote:

You can do something very similar in Ruby, using “fail” instead of “die”.
For example:

def open_file name
  f = File.open(name) or fail "couldn't open #{name}"
  return f
    end

–Mirian

···

On Tue, 22 Oct 2002 05:54:49 +0900, Bob X bobx@linuxmail.org wrote:

Cool…but what if serverlist.txt does not exist? The one thing I do like
about Perl is the “open file or die” test. I believe that I am “stuck” with
a rescue clause which is sometimes confusing for me (a newbie) to use when
it is located within a “def”.

Truth be told, you don’t need to “or die”. If you run the following
code (a minor modification to parameterize the filename), you’ll get
(assuming, of course, that serverlist2.txt doesn’t exist):

c:/home/Projects/Ruby/test.rb:4:in initialize': No such file or directory - "se rverlist2.txt" (Errno::ENOENT) from c:/home/Projects/Ruby/test.rb:4:in open’
from c:/home/Projects/Ruby/test.rb:4:in `load_server_list’
from c:/home/Projects/Ruby/test.rb:13

def load_server_list(filename)
servers =
File.open(filename).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
end

servers = load_server_list(‘serverlist2.txt’)
p servers.size, servers

To handle it as a caller, just replace the last two lines with
something like:

begin
fn = ‘serverlist2.txt’
servers = load_server_list(fn)
rescue Errno::ENOENT => ex
puts “Problem reading "#{fn}".\n\t#{ex.message}”
exit
end

File.open automatically raises an error. Where you might want to do
something different is to have your own FileNotFoundException, like
so:

class FileNotFoundException < RuntimeError
end

def load_server_list(filename)
servers =
File.exist?(filename) or raise FileNotFoundException, filename
File.open(filename).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
end

begin
servers = load_server_list(‘serverlist2.txt’)
rescue FileNotFoundException => fnf
puts “File ‘#{fnf.message}’ does not exist.”
exit
end

If there is anywhere that I think that Ruby’s class model is a bit
weak, it’s in the existence of and documentation of ‘standard’
exceptions. IMO, Errno::ENOENT is not what File.open should throw,
even though that’s the actual errno value received – it should throw
an appropriate readable exception (like FileNotFoundException) or
something like that.

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.10.21 at 17.17.05

···

On Tue, 22 Oct 2002 05:54:49 +0900, Bob X wrote:

Cool…but what if serverlist.txt does not exist? The one thing I do
like about Perl is the “open file or die” test. I believe that I am
“stuck” with a rescue clause which is sometimes confusing for me (a
newbie) to use when it is located within a “def”.

Hi –

···

On Tue, 22 Oct 2002, Mirian Crzig Lennox wrote:

On Tue, 22 Oct 2002 05:54:49 +0900, Bob X bobx@linuxmail.org wrote:

Cool…but what if serverlist.txt does not exist? The one thing I do like
about Perl is the “open file or die” test. I believe that I am “stuck” with
a rescue clause which is sometimes confusing for me (a newbie) to use when
it is located within a “def”.

You can do something very similar in Ruby, using “fail” instead of “die”.
For example:

def open_file name
f = File.open(name) or fail “couldn’t open #{name}”
return f
end

If an exception is raised by the open, though, the fail clause will
not be executed:

$ ruby -e ‘File.open(“NO_FILE”) or fail “Not reached”’
-e:1:in `open’: No such file or directory - “NO_FILE” (Errno::ENOENT)
from -e:1

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Mirian Crzig Lennox wrote:

Cool..but what if serverlist.txt does not exist? The one thing I do like
about Perl is the “open file or die” test. I believe that I am “stuck” with
a rescue clause which is sometimes confusing for me (a newbie) to use when
it is located within a “def”.

You can do something very similar in Ruby, using “fail” instead of “die”.
For example:

    def open_file name
      f = File.open(name) or fail "couldn't open #{name}"
      return f
    end

–Mirian

Note that this isn’t strictly necessary, unless you just want to provide your
own error message. Ruby will die at that point anyway if the file doesn’t
exist (and tell you why). No need to test.

f = File.open(“blah”)

Results in this:

in `open’: No such file or directory - “blah” (Errno::ENOENT)

Regards,

Dan

···

On Tue, 22 Oct 2002 05:54:49 +0900, Bob X bobx@linuxmail.org wrote:

“Austin Ziegler” austin@halostatue.ca wrote in message
news:20021021213317.JIBS2670.tomts5-srv.bellnexxia.net@hogwarts…

File.open automatically raises an error. Where you might want to do
something different is to have your own FileNotFoundException, like
so:

class FileNotFoundException < RuntimeError
end

def load_server_list(filename)
servers =
File.exist?(filename) or raise FileNotFoundException, filename
File.open(filename).each do |line|
next unless line =~ /^\S+$/
next if line =~ /^#.$/
servers << line.chomp.sub(/\s+#.
$/, ‘’)
end
servers
end

begin
servers = load_server_list(‘serverlist2.txt’)
rescue FileNotFoundException => fnf
puts “File ‘#{fnf.message}’ does not exist.”
exit
end
I tried this one…replacing ‘severlist2.txt’ with my actual filename. I get
the following:

D:/Robert/Projects/Ruby/serverchk.rb/serverchk.rb:37:in `load_server_list’:
wrong number of arguments(0 for 1) (ArgumentError)
from D:/Robert/Projects/Ruby/serverchk.rb/serverchk.rb:37

Bob

Hi,

If there is anywhere that I think that Ruby’s class model is a bit
weak, it’s in the existence of and documentation of ‘standard’
exceptions. IMO, Errno::ENOENT is not what File.open should throw,
even though that’s the actual errno value received – it should throw
an appropriate readable exception (like FileNotFoundException) or
something like that.

Like these?

class IO
module Error
NoSuchFileOrDirectory = Errno::ENOENT
PermissionDenied = Errno::EACCESS
OperationNotPermitted = Errno::EPERM
# …
end
end

···

At Tue, 22 Oct 2002 06:33:22 +0900, Austin Ziegler wrote:


Nobu Nakada

“Daniel Berger” djberge@qwest.com wrote in message
news:3DB473B8.9454B953@qwest.com

You can do something very similar in Ruby, using “fail” instead of
“die”.
For example:

    def open_file name
      f = File.open(name) or fail "couldn't open #{name}"
      return f
    end

–Mirian

Note that this isn’t strictly necessary, unless you just want to provide
your
own error message. Ruby will die at that point anyway if the file doesn’t
exist (and tell you why). No need to test.

f = File.open(“blah”)

Results in this:

in `open’: No such file or directory - “blah” (Errno::ENOENT)

Regards,

Dan

I would want to provide my own error message. I did not see the “fail”
option…grrrrr.