Perl: how to extend nested variable names

So far I have a text configuration file with variables in it:

foo=something
bar=${foo}

When processing in Perl, I replace the variables with the following expression:

s/(?<!\\)\$\{\s*([^\}\s]+(\s+[^\}\s]+)*)\s*\}/_replacement( $1 )/ge;

where _replacement () knows how to look for existing values.

Now I would like to extend the syntax of the text file so that I can do it recursively, for example:

platform=x86
foo_x86=somepc
foo_arm=somedevice
bar=${foo_${platform}}

where, when processing the last line, "$ {platform}" is first replaced with "x86", and the resulting "$ {foo_x86}" is replaced with "somepc".

I'm having trouble expanding my regex: I can't find a way to match} with the correct {. (Greedy will not work because the string may be "$ {a} $ {b}" and the unwanted one will not match.)

Ideas?

+4
2
sub expand {
   my ($vars, $s) = @_;
   $s =~ s{
      (
         \$\{
         (
            (?> [^\$\}]
            |   \$ (?! \{ )
            |   (?1)
            )++
         )
         \}
      )
   }{
      my $expanded = expand($vars, $2);
      $vars->{$expanded} // "\${$expanded}"    # /
   }xeg;
   return $s;
}

my $vars = {};
while (<DATA>) {
   chomp;
   my ($key, $val) = split(/=/, $_, 2);
   $vars->{$key} = expand($vars, $val);
}

print($vars->{bar}, "\n");

__DATA__
platform=x86
foo_x86=somepc
foo_arm=somedevice
bar=${foo_${platform}}
+3

, AppConfig, .

use AppConfig;

# create a new AppConfig object
my $config = AppConfig->new();

# define a variable
$config->set( 'foo', 'bar' );

# read configuration file
my $filename = 'your.conf';
$config->file( $filename );
+1

Source: https://habr.com/ru/post/1609379/


All Articles