[ConfigDirs]
A = /some/dir
B = /_#C#_/DeeperDir
C = /_#B#_/EvenDeeperDir
####
#!/usr/bin/perl
###############
## Libraries ##
###############
use strict;
use warnings;
use feature qw{ say };
##################
## User-defined ##
##################
# Define what makes a "template" variable
my $re_template = qr/_#([^#]+)#_/;
# The result of what you read from your config file, perhaps.
# Note that it's an ARRAY, since we'd like to prevent unintentional
# recursion (we should resolve template variables in the order in
# which they're seen).
my $a_params = [
[ 'A' => '/some/dir' ],
[ 'B' => '/_#A#_/DeeperDir' ],
[ 'C' => '/_#B#_/EvenDeeperDir' ],
];
##################
## Main program ##
##################
show_params($a_params, "[Before resolution]");
my $h_resolved = resolve_templates($a_params);
show_params($h_resolved, "[After resolution]");
#################
## Subroutines ##
#################
sub resolve_templates {
my ($a_params) = @_;
my $h_resolved = { };
for (my $i = 0; $i < @$a_params; $i++) {
my $idx = $i + 1;
my $a_keyval = $a_params->[$i];
my ($key, $tmpl) = @$a_keyval;
my $orig = $tmpl;
while ($tmpl =~ /$re_template/) {
my $ref = $1;
my $refval = $h_resolved->{$ref};
defined($refval) or die "Undefined ref '$ref' in '$orig'\n";
$tmpl =~ s/$re_template/$refval/g;
}
$h_resolved->{$key} = $tmpl;
}
return $h_resolved;
}
sub show_params {
my ($a_params, $msg) = @_;
$msg ||= "Parameters:";
say "-" x 79;
say $msg;
say "-" x 79;
if (ref $a_params eq 'HASH') {
# If a HASH was passed, turn it into an ARRAY
my $h_params = $a_params;
my @keys = sort { $a cmp $b } keys %$h_params;
$a_params = [ map { [ $_ => $h_params->{$_} ] } @keys ];
}
foreach my $a_keyval (@$a_params) {
my ($key, $val) = @$a_keyval;
my $text = "Parameter '$key' ";
$text .= "." x (32 - length($text));
$text .= " '$val'";
say $text;
}
say "";
}
##
##
-------------------------------------------------------------------------------
[Before resolution]
-------------------------------------------------------------------------------
Parameter 'A' .................. '/some/dir'
Parameter 'B' .................. '/_#A#_/DeeperDir'
Parameter 'C' .................. '/_#B#_/EvenDeeperDir'
-------------------------------------------------------------------------------
[After resolution]
-------------------------------------------------------------------------------
Parameter 'A' .................. '/some/dir'
Parameter 'B' .................. '//some/dir/DeeperDir'
Parameter 'C' .................. '///some/dir/DeeperDir/EvenDeeperDir'