在我的perl脚本中,我希望有两个版本的$config
目录:
my $config='$home/client/config';
和
my $config_resolved="$home/client/config";
但我想从$config_resolved
获取$config
,即类似的内容:
my $config_resolved=resolve_vars($config);
我怎样才能在perl中做这样的事情?
答案 0 :(得分:4)
来自Perl FAQ(每个Perl程序员应至少阅读一次):
How can I expand variables in text strings?
(由brian d foy提供)
如果你可以避免它,不要,或者你可以 使用模板系统,如Text :: Template或Template Toolkit, 那样做。您甚至可以完成工作
sprintf
或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
, 然后,变成'弗雷德',这就是字符串中剩下的东西:$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'
/e
也会默默地忽略违反严格的行为,取代undefined 带有空字符串的变量名。因为我正在使用/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;
答案 1 :(得分:2)
我使用eval
。
因此,您必须将所有标量(名称)替换为其值。
$config = 'stringone';
$boo = '$config/any/string';
$boo =~ s/(\$\w+)/eval($1)/eg;
print $boo;
答案 2 :(得分:1)
因为您使用my将其声明为私有变量,所以您也可以使用 / ee 修饰符。这可以找到声明在本地范围内的变量:
$boo =~ s/(\$\w+)/$1/eeg;
答案 3 :(得分:-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