Parsing of blocks (e.g. foo { bar })

T

Tor Houghton

Hi,

I'm wondering if there is a more elegant way of parsing "blocks" of data.

I have a configuration file, thus:

# comment

some.host.name {
; another comment
/etc/hostname.fxp0
/etc/hosts
/etc/mail
}

And I currently parse this using the following code:

while(<CONF>) {
next if(/^\s*(\#|;)|^\s*$/);
if(m#(\S+)\s+{# .. m#}#) {
$HOST=$1 if $1;
if(!/\{|\}/) {
print "add: $HOST ",$_;
}
}
}

Before I go "all out" and complete this section of the code using the
above technique, I was wondering if there was other (better) ways of doing
this (for one, I'm not sure how to catch out any errors in the file, for
instance:

some.host.here {
another.host {
/usr
/opt
}
/etc
/var/mail
}

... here the current code fails miserably. Mind you, I'm probably the only
one going to use this, so that may not be such a big deal :-> )

Thanks!

Tor
 
B

Brian Harnish

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

I'm wondering if there is a more elegant way of parsing "blocks" of data. [snip]
Before I go "all out" and complete this section of the code using the
above technique, I was wondering if there was other (better) ways of doing
this (for one, I'm not sure how to catch out any errors in the file, for
instance:

some.host.here {
another.host {
/usr
/opt
}
/etc
/var/mail
}

.. here the current code fails miserably. Mind you, I'm probably the only
one going to use this, so that may not be such a big deal :-> )

You didn't really say how you wanted to handle this condition. Is it a
valid condition, or can your program just abort?

If you need to handle that condition, then instead of using the scalar
".."'s flag, use a nesting counter:
my $nest = 0;
while(<CONF>) {
$nest++ if (/(\S+)\s*\{/);
$nest-- if (/\}/);
if($nest == 1) { # Or, $nest >= 1
# Handle conditions.
}
}

Actually, thinking about it, aborting would use very similar logic.

- Brian
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE/oStgiK/rA3tCpFYRAjpzAKCDOI/WgKFUnNmnG7Bf4hNuTSg1qQCgxvWm
vrQkYrxLEaFNq65GM8MwIEI=
=3Yc1
-----END PGP SIGNATURE-----
 
T

Tor Houghton

[snip]

You didn't really say how you wanted to handle this condition. Is it a
valid condition, or can your program just abort?

Hm. No, it's an invalid condition, so the program should just abort.
If you need to handle that condition, then instead of using the scalar
".."'s flag, use a nesting counter:
my $nest = 0;
while(<CONF>) {
$nest++ if (/(\S+)\s*\{/);
$nest-- if (/\}/);
if($nest == 1) { # Or, $nest >= 1
# Handle conditions.
}
}

Actually, thinking about it, aborting would use very similar logic.

Ah. I didn't think about doing it that way. Thanks!

Tor
 
D

David K. Wall

Tor Houghton said:
I'm wondering if there is a more elegant way of parsing "blocks"
of data.
[snip]

Before I go "all out" and complete this section of the code using
the above technique, I was wondering if there was other (better)
ways of doing this

If you're not tied to that particular format you could use
Config::Simple or one of the numerous other Config::* modules in the
CPAN.

But I may be revealing some ignorance here; your data may be the
output of another program that requires that format.
 
T

Tor Houghton

If you're not tied to that particular format you could use
Config::Simple or one of the numerous other Config::* modules in the
CPAN.

Thanks for the tip!

For this application, however, I need to make sure it'll work on a system
"out of the box", without the worry of whether a certain CPAN module needs
to be installed.

Tor
 

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,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top