如何用字符串替换字符串中哈希的所有键?

时间:2017-07-11 14:04:07

标签: perl hash

我正在使用可变系统编写脚本。该程序使用带有每个关键字值的哈希值,但我不知道如何继续 在替换字符串中的所有关键字时。

替换代码如下:

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是包含变量

的哈希

2 个答案:

答案 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,而不是这样做。你可能会   甚至可以使用sprintfprintf

完成工作
  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;