在很多配置文件中,都会牵涉到变量扩展,一个变量会有多少种可能的扩展结果,这在静态分析中非常重要。这里给出一个算法:
使用 perl 来表达(expand.pl),变量引用使用统一的形式:${varname}
Whoops, CSDN 竟然不支持 perl code, 用 ruby 做高亮,可能会有点问题
#!/usr/bin/env perl use strict; my %vars = (); # cross array array sub cross_aa($$) { my ($tx, $ty) = @_; my @res = (); for my $x (@$tx) { for my $y (@$ty) { push @res, $x.$y; } } return /@res; } sub expandexpr($) { my ($expr) = @_; my $res1 = [ "" ]; print "expand('$expr')/n"; while ($expr =~ m/(/$/{([/w.-]+)/})|([^/$]+)/g) { if ($3) { # join array scalar for (my $i = 0; $i < @$res1; ++$i) { $res1->[$i] .= $3; } } elsif ($1) { my @res2 = (); my $ty = $vars{$2}; for my $y (@$ty) { my $xy = cross_aa($res1, expandexpr($y)); push @res2, @$xy; } $res1 = /@res2; } else { print STDERR "bad expr=$expr, remain=$'/n"; } } return $res1; }
程序主控逻辑:
my @toExpand = (); for (my $i = 0; $i < @ARGV; ++$i) { if ($ARGV[$i] eq "-v") { push @toExpand, $ARGV[++$i]; } } while (<STDIN>) { if (m/([/w.-]+)/s*=(.*)$/g) { my $name = $1; my $val = $2; push @{$vars{$name}}, $val; } } for my $expr (@toExpand) { my $res = expandexpr("$expr"); print "expr:$expr/n"; for my $z (@$res) { print "/t:$z/n"; } }
使用一个简单的例子来测试一下(var.txt):
a=AA_ a=11_ b=BB_${a}${a} b=22_${a}${a} x=XX_${b}${a}${b} y=YY_${a}${x}
命令: ./expand.pl -v '$y' < var.txt
输出结果:
:YY_AA_XX_BB_AA_AA_AA_BB_AA_AA_ :YY_AA_XX_BB_AA_AA_AA_BB_11_AA_ :YY_AA_XX_BB_AA_AA_AA_BB_AA_11_ :YY_AA_XX_BB_AA_AA_AA_BB_11_11_ :YY_AA_XX_BB_11_AA_AA_BB_AA_AA_ :YY_AA_XX_BB_11_AA_AA_BB_11_AA_ :YY_AA_XX_BB_11_AA_AA_BB_AA_11_ ..................................... too long, 256 lines, you know why it is. :)
posted on 2011-06-26 00:04 能发波 阅读(165) 评论(0) 收藏 举报