HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Reading fields idiomatically

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fieldsreadingidiomatically

Problem

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/, ;
my @userparts = split(' ', $userline[0]);
my @user = $userparts[1];

seek($configfh, 0, 0);
my @pathline = grep /directory/, ;
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.

Solution

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

my %config;
while (my $line = ) {
    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 = ) {
    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.

Code Snippets

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

Context

StackExchange Code Review Q#20843, answer score: 2

Revisions (0)

No revisions yet.