Perl:如何扩展嵌套变量名

时间:2015-09-28 21:25:24

标签: regex perl

到目前为止,我有一个文本配置文件,其中包含变量:

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}”,非贪婪会不匹配。)

想法?

2 个答案:

答案 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 );