1

I have come up with the following, to first read the file and then put it into hash. = sign used as a delimiter.

sub get_config_value_by_key {
    my ( $module, $key ) = @_;

    my $config = &read_file_contents(
        $config_directory . '/' . $module . '/config' );
    my %config = $config =~ /(.*)=(.*)/g;

    return $config{$key};    
}

It works fine, except that, if I have equal sign in the value (which I use as delimiter), then it doesn't parse it correctly.

How to fix my regex to make it work properly, escaping = signs in the value?

Example of config lines:

key_1=Some value key_2=Some value with = sign which breaks it.

Ilia Ross
  • 13,086
  • 11
  • 53
  • 88
  • 2
    Don't use & when calling functions... it's so unneeded! Then, unless you have to solve this for homework or golfing, I'd look into split instead of solving it all with a single regexp. – polettix Jan 09 '16 at 10:08
  • 1
    @polettix No, not the home work, I do this for my _Authentic Theme_ (for Webmin). Webmin uses `&` in front of functions a lot. I'm not Perl expert yet. Why is `&` used for? – Ilia Ross Jan 09 '16 at 10:16
  • `Re: &` please check http://stackoverflow.com/questions/8912049/difference-between-function-and-function-in-perl – mpapec Jan 09 '16 at 10:50
  • 1
    @Сухой27 Thanks, pal! Will read carefully. – Ilia Ross Jan 09 '16 at 10:50
  • 1
    Summary is though: Only do it if you have a specific reason to. And even then, consider not doing so anyway, because it's probably less clear. – Sobrique Jan 09 '16 at 10:52
  • 1
    https://metacpan.org/pod/Config::Any – TLP Jan 09 '16 at 19:33

2 Answers2

3

You can use non greedy quantifier,

my %config = $config =~ /(.*?)=(.*)/g;
                          # ^_________ match smallest possible amount of chars
mpapec
  • 50,217
  • 8
  • 67
  • 127
  • I'd also not bother slurping config into an intermediate variable. This works just as well with `<$fh> =~ m/([^=]+)=(.*)/g;` (slightly different LHS, but that's a matter of taste) – Sobrique Jan 09 '16 at 10:49
  • 1
    Yeah, I know. I just assumed that was what `read_file_contents($filename);` was doing. – Sobrique Jan 09 '16 at 10:52
  • I'll check in a bit. Thanks, guys! – Ilia Ross Jan 09 '16 at 10:59
  • @Сухой27 Thanks, pal! However I don't understand why. What this `?` really does? – Ilia Ross Jan 09 '16 at 11:42
  • @IliaRostovtsev it makes a regex lazy (stop matching at first `=` occurrence) http://stackoverflow.com/a/2301298/223226 – mpapec Jan 10 '16 at 08:32
2

I would use something like this:

use warnings;
use strict; 
use Data::Dumper;

open my $in, '<', 'in.txt' or die $!;

my %data;
while(<$in>){
    my($key, $val) = split(/=/, $_, 2);  
    $data{$key} = $val; 
}

print Dumper \%data;

This will read in a file - here in.txt, split each line on = into a maximum of two parts, and then assign them to a hash key/value pair.

However your approach could be tweaked to allow non-greedy matching (.*?):

while(<$in>){   
    my ($key, $val) = $_ =~ /(.*?)=(.*)/;
    $data{$key} = $val;
    }
fugu
  • 6,417
  • 5
  • 40
  • 75
  • `split(/=/,` will split on second or third `=` sign in the line, right? I would like to see how my regex could be fixed. – Ilia Ross Jan 09 '16 at 10:30
  • @IliaRostovtsev - this should preserve the value string, as it only splits into two parts, and will stop after encountering the first `=` – fugu Jan 09 '16 at 10:34