3

在我的 perl 脚本中,我想要两个版本的$config目录:

my $config='$home/client/config';

my $config_resolved="$home/client/config";

但我想从中得到$config_resolved$config即这样的:

my $config_resolved=resolve_vars($config);

我怎么能在perl中做这样的事情?

4

4 回答 4

5

来自Perl FAQ(每个 Perl 程序员都应该至少阅读一次):

如何扩展文本字符串中的变量?

(由布赖恩·d·福伊提供)

如果可以避免,请不要这样做,或者如果您可以使用模板系统,例如 Text::Template 或 Template Toolkit,请改为这样做。您甚至可以使用 sprintfor完成工作printf

my $string = sprintf 'Say hello to %s and %s', $foo, $bar;

但是,对于我不想提取完整模板系统的一次性简单情况,我将使用一个包含两个 Perl 标量变量的字符串。在这个例子中,我想扩展$foo$bar到他们的变量值:

my $foo = 'Fred';
my $bar = 'Barney';
$string = 'Say hello to $foo and $bar';

我可以做到这一点的一种方法涉及替换运算符和双/e标志。第一个在替换端/e进行评估$1并将其转换为$foo. 第二个以它的值/e开头$foo并替换它。$foo,然后变成“Fred”,这就是字符串中剩下的内容:

$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'

/e也会默默地忽略违反严格的,用空字符串替换未定义的变量名。因为我使用了/e标志(甚至两次!),所以我遇到了与字符串形式的 eval 相同的安全问题。如果 有什么奇怪的东西$foo,也许像@{[ system "rm -rf /" ]},那么我可能会给自己惹上麻烦。

为了解决安全问题,我还可以从哈希中提取值,而不是评估变量名。使用单个/e,我可以检查哈希以确保该值存在,如果不存在,我可以用标记替换缺失的值,在这种情况下 ???表示我错过了一些东西:

my $string = 'This has $foo and $bar';
my %Replacements = (
    foo  => 'Fred',
    );
# $string =~ s/\$(\w+)/$Replacements{$1}/g;

$string =~ s/\$(\w+)/
            exists $Replacements{$1} ? $Replacements{$1} : '???'
            /eg;
print $string;
于 2012-06-26T09:43:13.210 回答
2

我用eval这个。因此,您必须用它们的值替换所有标量(它们的名称)。

$config = 'stringone';
$boo = '$config/any/string';
$boo =~ s/(\$\w+)/eval($1)/eg;
print $boo;
于 2012-06-26T06:36:16.640 回答
1

因为您使用 my 将其声明为私有变量,所以您不妨使用/ee修饰符。这可以找到声明在本地范围内的变量:

$boo =~ s/(\$\w+)/$1/eeg;
于 2012-06-26T07:23:40.280 回答
-1

这是由s///.

在下面的程序中,第一个/e计算字符串$1以获取$home,而第二个计算$home获取变量的值HOME

use strict;

my $home = 'HOME';

my $config = '$home/client/config';

my $config_resolved = resolve_vars($config);

print $config_resolved, "\n";

sub resolve_vars {
  (my $str = shift) =~ s/(\$\w+)/$1/eeg;
  return $str;
}

输出

HOME/client/config
于 2012-06-26T11:50:37.860 回答