Match everything between double quotes, multiple capture groups

Viewed 186

I'm trying to leverage regex to extract information that exists between double quotes in every line of a configuration file. I'm okay with some basic level regex, but when it comes to complex ones; especially involving capture groups I keep running into brick walls despite trying to test and research via regex101.com.

my $text = '
"Key1" = { StuffIDontCareAbout = "Value1" },
"Key2" = { StuffIDontCareAbout = "Value2" },
"Key3" = { StuffIDontCareAbout = "Value3" },
"Key4" = { StuffIDontCareAbout = "Value4" },';
my %hash = undef;
for (split/\n/,$text) {
  my $pattern = qr/(")(?:(?=\\?))\2.)*?\1/;
  $hash{$1} = $2 if (/$pattern/);
}
print Dumper \%hash;

On regex101.com the information I care about is highlighted; however in my perl script $1 = " & $2 = null.

I think I need to match quotes with non-capture groups so that the first and second capture group is everything between them, however I can't figure it out.

Thanks in advance.

1 Answers

If there can never be nested quotes, never ever, then you can match a sequence of non-quote characters between quotes, and do that "globally" (/g modifier), so all such instances in the string. One way

my %hash;

foreach my $line (split /\n/, $text) {
    if (my ($key, $value) = $line =~ /"([^"]+)"/g) {
        $hash{$key} = $value;
    }
}

There are a number of other ways to check that you got two (and precisely two?) matches, and to organize the rest of the processing.†

Note that there is no need for undef to be assigned to a variable when it is declared, and it doesn't do anything; a new my variable (unassigned) is undef.

All code tested with $text copied verbatim from the question.


† As a curiosity, can do it all in one line

my %hash = map { /"([^"]+)"/g } split /\n/, $text;

This isn't a good practice, for one since we can't check anything along the way.

Related