# Reading variables in a file

**URL:** <https://www.ruby-forum.com/t/reading-variables-in-a-file/73845>\
**Category:** Ruby\
**Created:** [October 27, 2006, 3:30pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845 "2006-10-27T15:30:47Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 3:30pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/1 "2006-10-27T15:30:47Z")

</div>

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.

* * *

---

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 3:39pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/2 "2006-10-27T15:39:38Z")

</div>

On 27/10/06, Ooo G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> line). How can i do this? and how can i write them into a file??  
> Thank you in advance.
> 
> * * *
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).  
> File.open(file) do |f|  
> f.each\_line do |line|  
> name,order,year = \*line.split  
> end  
> end

Farrel

---

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 3:40pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/3 "2006-10-27T15:40:44Z")

</div>

Ooo G. wrote:

> 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]

---

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 3:45pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/4 "2006-10-27T15:45:40Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 4:00pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/5 "2006-10-27T16:00:40Z")

</div>

Ooo G. wrote:

> 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, :order =\> $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[:order]}, 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[:order]} #{person[:year]}”

# write string to file

end  
end

---

<div class="post-metadata">

**Author:** ![ogrecio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/o/258eb7/32.png) [@ogrecio](https://www.ruby-forum.com/u/ogrecio)\
**Post date:** [October 27, 2006, 4:27pm UTC](https://www.ruby-forum.com/t/reading-variables-in-a-file/73845/6 "2006-10-27T16:27:44Z")

</div>

On Fri, 27 Oct 2006, Ooo G. wrote:

> 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/](http://formatr.sourceforge.net/)

```
    Hugh

```
