# Help parsing simple structured data

**URL:** <https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247>\
**Category:** Ruby\
**Created:** [August 29, 2007, 7:38am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247 "2007-08-29T07:38:27Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 7:38am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/1 "2007-08-29T07:38:27Z")

</div>

I’m rather new to Ruby and am trying to figure out how to parse some  
structured data… This is pretty much the most common problem I run into  
and it’d be _really_ helpful to see an example to wrap my head around  
blocks  
& hashes

The data I’m working with is the output of `df -h` which looks like this  
:

Filesystem Size Used Avail Use% Mounted on  
/dev/md0 9.9G 1.6G 7.8G 17% /  
/dev/md1 60G 154M 57G 1% /data  
/dev/sda1 99M 12M 83M 13% /boot

In the end what I’d like to end up with is to be able to say print  
hash[md0(size)] and have it  
return 9.9G or hash[sda1(Mount)] and have it show the mountpoint of  
/boot

If anyone could help I’d really appreciate it.

Craig

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 8:05am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/2 "2007-08-29T08:05:30Z")

</div>

Nuby R. wrote:

> /dev/md1 60G 154M 57G 1% /data  
> /dev/sda1 99M 12M 83M 13% /boot
> 
> In the end what I’d like to end up with is to be able to say print  
> hash[md0(size)] and have it  
> return 9.9G or hash[sda1(Mount)] and have it show the mountpoint of /boot
> 
> If anyone could help I’d really appreciate it.
> 
> Craig

Try this:

rows = `df -h`.split("\n")[1…-1]  
hash = Hash.new {|hash, key| hash[key] = {}}  
rows.each do |row|  
data = row.split /\s+/  
device = data[0].sub(%r|^/dev/|, “”)  
%w{size used avail use mount}.each\_with\_index do |field, column|  
hash[device][field] = data[column+1]  
end  
end

After running it, you should be able to find your data in  
hash[“md0”][“size”] or hash[“sda1”][“mount”].

Does this work for you?

Dan

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 8:10am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/3 "2007-08-29T08:10:30Z")

</div>

Dan,

That works perfectly, thank you a lot! This type of data I end up  
dealing  
with day-in and day-out, and this will help a lot.

Craig

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 8:26am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/4 "2007-08-29T08:26:33Z")

</div>

Nuby R. wrote:

> > > structured data… This is pretty much the most common problem I run into  
> > > /dev/sda1 99M 12M 83M 13% /boot
> > 
> > After running it, you should be able to find your data in  
> > hash[“md0”][“size”] or hash[“sda1”][“mount”].
> > 
> > Does this work for you?
> > 
> > Dan

Craig,

By the way, I just realized that my script assumes that the mount point  
has no spaces. Nothing horrible will happen if it does, but  
hash[device][“mount”] will only contain the first word, like “/d/My” of  
“/d/My Documents”. If you want to fix that, you could replace a few of  
the lines in the above script with these:

> > %w{size used avail use}.each\_with\_index do |field, column|  
> > hash[device][field] = data[column+1]  
> > end  
> > hash[device][mount] = data[5…-1].join(" ")

Have fun,  
Dan

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 8:46am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/5 "2007-08-29T08:46:34Z")

</div>

In my situation it’ll always be safe to assume there are no mount  
points,  
but I’ll grab your code anyways in case I ever run it on a windows or  
mac  
box.

BTW, here’s the code I’m working on, thanks for the tidbit, this little  
bit  
of processing is the bit of code I use most in my daily life, and the  
hardest for me to wrap my head around when I play with new langauges.

#!/usr/bin/env ruby

require ‘rubygems’  
require ‘getoptlong’  
require ‘net/ssh’

opts = GetoptLong.new(  
[“–host”, “-h”, GetoptLong::REQUIRED\_ARGUMENT]  
)

hostname = nil  
opts.each do |opt, arg|  
case opt  
when ‘–host’  
hostname = arg  
end  
end

if hostname == nil  
puts “Missing --host argument”  
puts “usage: `ssh-test.rb --host hostname”  
exit 0  
end

Net::SSH.start( hostname,  
:password=\>‘somepassword’,  
:port=\>22,  
:username=\>‘rubyuser’  
) do |session|  
shell = session.shell.open  
shell.df “-h”  
sleep 0.5

```
              disks = shell.stdout.split("\n")[1..-1] while 

```

shell.stdout  
?

```
              hash = Hash.new {|hash, key| hash[key] = {}}
              disks.each do |disk|
                data = disk.split /\s+/
                device = data[0].sub(%r|^/dev/|, "")
                %w{size used avail use mount}.each_with_index do

```

|field, column|  
hash[device][field] = data[column+1]  
end  
end

```
              print hash["md0"]["mount"]
              puts "\n"

```

end

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 10:39am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/6 "2007-08-29T10:39:45Z")

</div>

From: Nuby R. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

# of processing is the bit of code I use most in my daily life, and the

# hardest for me to wrap my head around when I play with new langauges.

you sound like an admin or you do admin tasks daily.

just want to tell you that there’s a gem called ruport used for  
reporting task. …just in case it may help you.

this is just a simple example. i snipped the initial echos fr irb. the  
last outputs will give you an idea…

so,

> require ‘rubygems’  
> require ‘ruport’

> data =`df -h`.split “\n”  
> header=data.shift.split " ",6  
> data = data.map{|line| line.split}  
> report = Ruport::Data::Table.new :data =\> data, :column\_names =\> header

> puts report  
> ±------------------------------------------------------------------------------+  
> | Filesystem | Size | Used | Avail | Use% | Mounted on |  
> ±------------------------------------------------------------------------------+  
> | /dev/hda1 | 3.8G | 3.1G | 566M | 85% | / |  
> | varrun | 125M | 68K | 125M | 1% | /var/run |  
> | varlock | 125M | 4.0K | 125M | 1% | /var/lock |  
> | udev | 125M | 76K | 125M | 1% | /dev |  
> | devshm | 125M | 0 | 125M | 0% | /dev/shm |  
> | lrm | 125M | 18M | 107M | 15% | /lib/modules/2.6.15-28-686/volatile |  
> | /dev/hdb1 | 19G | 6.9G | 13G | 36% | /disk2 |  
> | /dev/hdd1 | 2.0G | 731M | 1.3G | 37% | /disk3-1 |  
> | /dev/hdd2 | 2.1G | 65M | 1.9G | 4% | /disk3-2 |  
> ±------------------------------------------------------------------------------+  
> =\> nil

> puts report.column(“Filesystem”)  
> /dev/hda1  
> varrun  
> varlock  
> udev  
> devshm  
> lrm  
> /dev/hdb1  
> /dev/hdd1  
> /dev/hdd2  
> =\> nil

> puts report.column(“Size”)  
> 3.8G  
> 125M  
> 125M  
> 125M  
> 125M  
> 125M  
> 19G  
> 2.0G  
> 2.1G  
> =\> nil

there are a lot of fxns in ruport that allow you to sum on columns, swap  
them, remove/add columns, drill down on records, etc…

many thanks to GBrown and MMilner, et al for ruport.  
kind regards -botp

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 3:25pm UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/7 "2007-08-29T15:25:40Z")

</div>

On Aug 29, 7:49 am, Thibaut Barrère [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > just want to tell you that there’s a gem calledruportused for reporting task. …just in case it may help you.
> 
> +1 forruport, it makes these things very easy to achieve, with less  
> code.
> 
> FWIW, you’ll get extra features at no cost, like:
> 
> File.open(‘report.pdf’,‘w’) do |file|  
> file \<\< table.to\_pdf  
> end

Or as of today:

table.to\_pdf(:file =\> "report.pdf)

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 29, 2007, 1:52pm UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/8 "2007-08-29T13:52:14Z")

</div>

> just want to tell you that there’s a gem called ruport used for reporting task. …just in case it may help you.

+1 for ruport, it makes these things very easy to achieve, with less  
code.

FWIW, you’ll get extra features at no cost, like:

File.open(‘report.pdf’,‘w’) do |file|  
file \<\< table.to\_pdf  
end

cheers

Thibaut

---

<div class="post-metadata">

**Author:** ![Nuby\_R](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/c5a1d2/32.png) [@Nuby\_R](https://www.ruby-forum.com/u/Nuby_R)\
**Post date:** [August 30, 2007, 9:57am UTC](https://www.ruby-forum.com/t/help-parsing-simple-structured-data/113247/9 "2007-08-30T09:57:34Z")

</div>

Oh man this is awesome. I love ruby, I spent the last hour playing with  
ruport, and am in love with it’s simplicity… The reason I’m learning  
Ruby  
is to make it easier for me to get off my butt and write reports.
