到目前为止,我有一个文本配置文件,其中包含变量:
foo=something
bar=${foo}
在Perl中处理它时,我用这样的正则表达式替换变量:
s/(?<!\\)\$\{\s*([^\}\s]+(\s+[^\}\s]+)*)\s*\}/_replacement( $1 )/ge;
其中_replacement()知道如何查找现有值。
现在我希望能够扩展文本文件的语法,以便我可以递归地执行此操作,如下所示:
platform=x86
foo_x86=somepc
foo_arm=somedevice
bar=${foo_${platform}}
当处理最后一行时,“$ {platform}”首先被替换为“x86”,然后生成的“$ {foo_x86}”被替换为“somepc”。
我在扩展我的正则表达式时遇到了麻烦:我似乎无法找到一种方法来匹配}和正确的{。 (贪婪不会起作用,因为字符串可能是“$ {a} $ {b}”,非贪婪会不匹配。)
想法?
答案 0 :(得分:3)
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}}
答案 1 :(得分:1)
您的输入文件与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 );