我正在使用可变系统编写脚本。该程序使用带有每个关键字值的哈希值,但我不知道如何继续 在替换字符串中的所有关键字时。
替换代码如下:
while ( ($key, $value) = each %variables_hash ) {
if ( -1 != index($CMD, $key) ) {
# Here should be the code that I cant think how to do
}
}
$CMD
是输入字符串,和
%variables_hash
是包含变量
答案 0 :(得分:2)
您可以使用substr替换子字符串。我使用while
代替if
,因此您可以替换多次出现。 length $key
用于确定要替换的子字符串的长度。
#!/usr/bin/perl
use warnings;
use strict;
my %variables_hash = (
_number => 123,
_name => 'John Smith',
);
my $CMD = 'INSERT INTO customers (name, code) VALUES("_name", _number)';
while (my ($key, $value) = each %variables_hash) {
while (-1 != ( my $pos = index $CMD, $key )) {
substr $CMD, $pos, length $key, $value;
}
}
print $CMD, "\n";
另一个选择是使用替换(请参阅perlop)或模板(例如Template)。
my $regex = join '|', map quotemeta, keys %variables_hash;
$CMD =~ s/($regex)/$variables_hash{$1}/g;
请注意,如果一个变量名是另一个变量名的子字符串,您可能希望将它们从最长到最短处理(同样适用于substr
解决方案);所以你可能需要说
map quotemeta, sort { length $b <=> length $a } keys %variables_hash;
请注意,变量不能以下划线开头,但不需要它们,因为变量包含在模板标记中,因此在引用列名时不会意外地替换name
。 / p>
use Template;
my %variables_hash = (
number => 123,
name => 'John Smith',
);
my $CMD = 'INSERT INTO customers (name, code) VALUES("[% name %]", [% number %])';
my $template = 'Template'->new;
$template->process(\$CMD, \%variables_hash);
答案 1 :(得分:2)
如果您将成为Perl程序员,那么您需要阅读Perl常见问题解答。 This is from perlfaq4.
如何在文本字符串中扩展变量?
(由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';
我可以这样做的一种方法是使用替换运算符和double
/e
标志。第一个/e
评估替换方的$1
和 把它变成$foo
。第二个/e
以$foo
开头并替换 它的价值。然后,$foo
变成'弗雷德',那就是最终 字符串中还剩下什么:$string =~ s/(\$\w+)/$1/eeg; # 'Say hello to Fred and Barney'
/e
也会默默地忽略违反严格替换的行为 带有空字符串的未定义变量名。因为我正在使用/e
标志(甚至两次!),我有所有相同的安全问题 以字符串形式使用eval
。如果有奇怪的东西$foo
,或许类似于@{[ system "rm -rf /" ]}
,我可以 让自己陷入困境。为了解决安全问题,我还可以从a中提取值 哈希而不是评估变量名称。使用单
/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;