reading variables in a file

O

Ooo Grec

I'm thinking of migrating from Fortran to Ruby. Do you think i should go
ahead??
First problem i have.
How to read a file with several fields? This means:
Imagine a file:
Peter4 1990
Sam 3 1980
Grac6 1991

I would like to read for each line:name, order and year (3 variables per
line). How can i do this? and how can i write them into a file??
Thank you in advance.
 
F

Farrel Lifson

I'm thinking of migrating from Fortran to Ruby. Do you think i should go
ahead??
First problem i have.
How to read a file with several fields? This means:
Imagine a file:
Peter4 1990
Sam 3 1980
Grac6 1991

I would like to read for each line:name, order and year (3 variables per
line). How can i do this? and how can i write them into a file??
Thank you in advance.
File.open(file) do |f|
f.each_line do |line|
name,order,year = *line.split
end
end

Farrel
 
B

Brad Tilley

Ooo said:
I would like to read for each line:name, order and year (3 variables per
line). How can i do this?


String.split will work if there is whitespace in between each item:

irb(main):001:0> x = 'Peter 4 1990'
=> "Peter 4 1990"
irb(main):002:0> x.split
=> ["Peter", "4", "1990"]
irb(main):003:0> quit

Now, you have an array that contains [name, order, year]
 
N

naPOLeon

I would do this that way:

var = Array.new
File.open("file.txt", "r") do |file|
file.each_line do |line|
var << line.split
end
end

Now you have an array to play with.
If you want to access a specific line, use
sth = var[0] => ["Peter", "4", 1990"]

Or a single variable:

var[0][0] => "Peter"
var[2][2] => "1991"

If you want to write them into an other file, just write:

File.open("write.txt", "a+") do |file|
file << var
end

Hope thats, what you were looking for,

naPOLeon
 
H

Hugh Sasse

I'm thinking of migrating from Fortran to Ruby. Do you think i should go
ahead??

You might just want to do the text processing in ruby, and invoke
fortran programs for the numeric bits.

You've got answers to the other bit. If you want to write fixed
length records, which IIRC Fortran is good at reading, you can
use (if you've done make install-doc you can get this with `ri pack`):

------------------------------------------------------------- Array#pack
arr.pack ( aTemplateString ) -> aBinaryString
------------------------------------------------------------------------
Packs the contents of _arr_ into a binary sequence according to the
directives in _aTemplateString_ (see the table below) Directives
``A,'' ``a,'' and ``Z'' may be followed by a count, which gives the
width of the resulting field. The remaining directives also may
take a count, indicating the number of array elements to convert.
If the count is an asterisk (``+*+''), all remaining array elements
will be converted. Any of the directives ``+sSiIlL+'' may be
followed by an underscore (``+_+'') to use the underlying
platform's native size for the specified type; otherwise, they use
a platform-independent size. Spaces are ignored in the template
string. See also +String#unpack+.

a = [ "a", "b", "c" ]
n = [ 65, 66, 67 ]
a.pack("A3A3A3") #=> "a b c "
a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000"
n.pack("ccc") #=> "ABC"

Directives for +pack+.

Directive Meaning
---------------------------------------------------------------
@ | Moves to absolute position
A | ASCII string (space padded, count is width)
a | ASCII string (null padded, count is width)
B | Bit string (descending bit order)
b | Bit string (ascending bit order)
C | Unsigned char
c | Char
D, d | Double-precision float, native format
E | Double-precision float, little-endian byte order
e | Single-precision float, little-endian byte order
F, f | Single-precision float, native format
G | Double-precision float, network (big-endian) byte order
g | Single-precision float, network (big-endian) byte order
H | Hex string (high nibble first)
h | Hex string (low nibble first)
I | Unsigned integer
i | Integer
L | Unsigned long
l | Long
M | Quoted printable, MIME encoding (see RFC2045)
m | Base64 encoded string
N | Long, network (big-endian) byte order
n | Short, network (big-endian) byte-order
P | Pointer to a structure (fixed-length string)
p | Pointer to a null-terminated string
Q, q | 64-bit number
S | Unsigned short
s | Short
U | UTF-8
u | UU-encoded string
V | Long, little-endian byte order
v | Short, little-endian byte order
w | BER-compressed integer\fnm
X | Back up a byte
x | Null byte
Z | Same as ``a'', except that null is added with *



or you can look for the FormatR package:
http://formatr.sourceforge.net/

Hugh
 
C

Chris Gernon

Ooo said:
I'm thinking of migrating from Fortran to Ruby. Do you think i should go ahead??

That entirely depends on what the application is, if you currently use a
number of Fortran libraries, etc. However, I say it never hurts to learn
another language (gives you another tool in your tool belt), and Ruby is
one of the easiest to learn and most useful out there.
First problem i have.
How to read a file with several fields? This means:
Imagine a file:
Peter4 1990
Sam 3 1980
Grac6 1991

A typical Ruby program to do this would look something like this. This
is pretty simple, so I combined reading from the file and writing to a
new file into the same program. Also, the real "Ruby Way" to do this
would be to create a Person class with name, order, and year attributes
... but I figured a "quick and dirty" approach of storing the values in
a hash would work for a simple example like this. (Note that # starts
comments, except inside double quotes, where #{} inserts a variable or
expression inside the double-quoted string). Hope this helps!

#!/usr/bin/env ruby -w

INPUT_FILE = 'data.txt'
OUTPUT_FILE = 'new_data.txt'

people = [] #empty array
File.open(INPUT_FILE) do |data| # open file for reading
data.each do |line| # for each line ...
# if line matches (text containing no digits, then 1 or more digits,
then a space, then 4 digits)
if line =~ /^(\D*)(\d+) (\d\d\d\d)$/
person = {:name => $1.strip, :eek:rder => $2, :year => $3} # capture
matched values in a hash
people << person # add the person hash to the people array
else
puts "Read line that was not in expected format!"
end
end
end
puts "read #{INPUT_FILE} file" # puts: put string (print to stdout)
puts 'Data read:'
people.each do |person| # for each person hash in the people array ...
puts "Name: #{person[:name]}, Order: #{person[:eek:rder]}, Year:
#{person[:year]}"
end

File.open(OUTPUT_FILE, 'w') do |new_data| # open file for writing
people.each do |person| # for each person hash in the people array ...
new_data.puts "#{person[:name]} #{person[:eek:rder]} #{person[:year]}"
# write string to file
end
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top