# Parsing files

**URL:** <https://www.ruby-forum.com/t/parsing-files/96046>\
**Category:** Ruby\
**Created:** [June 23, 2006, 9:09pm UTC](https://www.ruby-forum.com/t/parsing-files/96046 "2006-06-23T21:09:55Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![john\_old](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9f8e36/32.png) [@john\_old](https://www.ruby-forum.com/u/john_old)\
**Post date:** [June 23, 2006, 9:09pm UTC](https://www.ruby-forum.com/t/parsing-files/96046/1 "2006-06-23T21:09:55Z")

</div>

One thing I find myself doing over and over is parsing some type of  
text file and making something sensible out of it.  
As yet, I haven’t found a good solution (I’m probably missing some  
gems or modules someone has already created). I think that, though  
BNF is fine for writing compilers, it’s a little more complex than  
need be for parsing files. I’ve recently created a solution (with  
thanks to the author of OptionParser for the modus operandi). The  
following is part of a routine for parsing some really horrid SAP R/3  
files:

# horrid file

VERSION  
100  
DEBUG  
0  
SYSTEM  
PRD  
HOSTNAME  
198.203.4.202  
SYSNUM  
01  
…  
CONTAINER\_ELEMENT\_INFO  
BASEUNITOFMEASURE 000002003C  
CONTAINER\_ELEMENT\_VALUE  
EA  
CONTAINER\_ELEMENT\_INFO  
CAUSECODEGROUP 000000008C  
CONTAINER\_ELEMENT\_VALUE  
CES

# Parsing routine using my parser module

```
 DOTTED_QUAD_RE = '(\d+)\.(\d+)\.(\d+)\.(\d+)'

```

…  
@wrk = RegexpParser.new

```
 @wrk.on( /VERSION\n(\d+)\n/m ) { |version| @version = version }
 @wrk.on( /DEBUG\n(\d+)\n/m ) { |debug| @debug = debug }
 @wrk.on( /SYSTEM\n([^\n]+)\n/m ) { |system| @system = system }
 @wrk.on( /HOSTNAME\n#{DOTTED_QUAD_RE}\n/m ) { |hostname|
   @hostname = hostname
 }

```

…  
@wrk.on(  
/CONTAINER\_ELEMENT\_INFO\n  
([^\s]+) (?# element name )  
\s+  
(\d{4}) (?# unknown digits )  
(\d{2}) (?# index number)  
(\d{3}) (?# field width )  
C\n (?# trailing literal C )  
CONTAINER\_ELEMENT\_VALUE\n  
([^\n]+)\n (?# value of the element )  
/mx  
) { |name, unknown, index, width, value|  
case name  
when /REQUIREDSTARTDATE/, /REQUIREDEND/, /DATESENT/,  
/CONTRACTSTARTDATE/, /CONTRACTENDDATE/  
value = yyyymmdd\_to\_datetime(value)  
…  
if @elements[name].nil?  
@elements[name] = []  
end  
@elements[name][index] = value  
}

Is there a better way to do this?  
Should I share my parser with others (via RubyForge or the like)?

Thanks,  
JJ

* * *

Help everyone. If you can’t do that, then at least be nice.

---

<div class="post-metadata">

**Author:** ![john\_old](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/9f8e36/32.png) [@john\_old](https://www.ruby-forum.com/u/john_old)\
**Post date:** [June 23, 2006, 10:16pm UTC](https://www.ruby-forum.com/t/parsing-files/96046/2 "2006-06-23T22:16:09Z")

</div>

On Sat, 2006-06-24 at 04:09 +0900, John J. wrote:

> Should I share my parser with others (via RubyForge or the like)?

Looks nifty to me!

Re the EBNF route, you’ve probably seen RACC already?

[http://i.loveruby.net/en/projects/racc/](http://i.loveruby.net/en/projects/racc/)

Yours,

Tom
