Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

This technique is more general than just for config files which is why I'm not using Config::Any in this example.

I have a config file with lines like this:

userid foo-admin # foo-comment
directory /some/dir # bar-comment

And I'm using some very awkward code to get the values.

my @userline = grep /userid/, <$configfh>;
my @userparts = split(' ', $userline[0]);
my @user = $userparts[1];

seek($configfh, 0, 0);
my @pathline = grep /directory/, <$configfh>;
my @pathparts = split(' ', $pathline[0]);
my $path = $pathparts[1];

It works! But man, is it ugly. There's got to be a clearer way to extract the values I want from the file.

share|improve this question
1  
even though you may not just be using it for "config" files, can't you still use a module like Config::Any? –  stevenl Jan 24 '13 at 16:33

2 Answers 2

up vote 0 down vote accepted

If you're determined to avoid using a module for this, how about something like the following:

my %config;
while (my $line = <$configfh>) {
    chomp $line;  # Strip trailing linefeeds, you probably don't want them there
    my @fields = split(/\s+/, $line);
    $config{$fields[0]} = $fields[1] if $fields[0];
}

But perhaps your config file may contain values with whitespace? If you can require those to be wrapped in quotes, or some other convenient character, that's not a problem.

my %config;
while (my $line = <$configfh>) {
    chomp $line;
    my ($field, $value) = split(/\s+/, $line, 2);  # The 2 is how many parts to split into
    if ($value =~ /^\"/) {
        $value =~ s/^\"(.*?)\"/$1/;  # Keep what's in the first pair of quotes
    } else {
        ($value, undef) = split(/\s+/, $value);  # Drop trailing comments
    }
    $config{$field} = $value if $field;
}

(Note that the " characters don't actually need escaping, but the syntax highlighting breaks otherwise...)

Obviously there are other possible cases which this doesn't cover, but if your use cases are that extensive, you should probably reconsider and use a module.

share|improve this answer
1  
This is not a valid script (syntax error in line 2: my variable is defined inside parens in while). Also, it's not bulletproof - adds empty lines to %config. –  Xaerxess Jan 25 '13 at 1:06
    
Right on both counts. The while bug is a bit embarrassing actually! Editing to correct, with thanks for pointing it out. –  Greg D'Arcy Jan 25 '13 at 9:19

Your config file almost matches the style of Config::Simple. This module is easy to use and needs no extra configuration to read your key-value pairs separated by white-space.

But, I said almost because you will have a problem with the inline comments. The comments actually become part of the value ... so they could be filtered off later but that seems risky and bothersome.

If you could tolerate keeping your comments on a separate line, the following should work for you.

use Config::Simple;
my $cfg = new Config::Simple($configfh);
my $userid = $cfg->param('userid');
my $directory = $cfg->param('$directory');

It's also possible to pull in the entire config file to a single hash directly from the first call (this is how I use it):

Config::Simple->import_from($configfh, \%cfg);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.