简体   繁体   English

如何将字符串中哈希的所有键替换为其值?

[英]How can I replace all keys of a hash in a string with their values?

I am coding a script with a variable system. 我正在用可变系统编码脚本。 The program uses a hash with a value for each keyword, but I don't know how to continue when it comes to replacing all keywords in a string. 该程序为每个关键字使用一个带有值的哈希,但是当替换字符串中的所有关键字时,我不知道如何继续。

The code of the replacement looks like: 替换代码如下:

while ( ($key, $value) = each %variables_hash ) {
    if ( -1 != index($CMD, $key) ) {
        # Here should be the code that I cant think how to do
    }
}

$CMD is the input string, and %variables_hash is the hash that contains the variabless $CMD是输入字符串, %variables_hash是包含变量的哈希

You can use substr to replace the substring. 您可以使用substr替换子字符串。 I used while instead of if so you can replace multiple occurrences. 我用while代替if来代替多次出现。 length $key is used to determine the length of the substring to replace. 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";

Another option would be to use substitution (see perlop ), or a Template (eg Template ). 另一种选择是使用替换(请参阅perlop )或模板(例如Template )。

Substitution: 替代:

my $regex = join '|', map quotemeta, keys %variables_hash;

$CMD =~ s/($regex)/$variables_hash{$1}/g;

Note that if one variable name is a substring of another, you probably want to process them from the longest to the shortest (the same applies to the substr solution); 请注意,如果一个变量名是另一个变量的子串,则可能要从最长到最短进行处理( substr解决方案也是如此); so you might need to say 所以你可能需要说

map quotemeta, sort { length $b <=> length $a } keys %variables_hash;

Template: 模板:

Note that variables can't start with underscores, but they aren't needed, as the variables are included in template tags, so you won't accidentally replace name when it refers to the column name. 需要注意的是变量不能用下划线开始,但他们没有必要,因为这些变量都包含在模板标签,这样你就不会意外地取代name时,它指的是列名。

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);

If you're going to be a Perl programmer, then you need to read the Perl FAQ. 如果您要成为Perl程序员,那么您需要阅读Perl FAQ。 This is from perlfaq4. 这是来自perlfaq4。

How can I expand variables in text strings? 如何扩展文本字符串中的变量?

(contributed by brian d foy) (由brian d foy贡献)

If you can avoid it, don't, or if you can use a templating system, such as Text::Template or Template Toolkit, do that instead. 如果可以避免,请不要这样做,或者可以使用模板系统,例如Text :: Template或Template Toolkit,请改用该方法。 You might even be able to get the job done with sprintf or printf : 您甚至可以使用sprintfprintf完成工作:

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

However, for the one-off simple case where I don't want to pull out a full templating system, I'll use a string that has two Perl scalar variables in it. 但是,对于一次性的简单情况,我不想使用完整的模板系统,我将使用其中包含两个Perl标量变量的字符串。 In this example, I want to expand $foo and $bar to their variable's values: 在此示例中,我想将$foo$bar扩展为其变量的值:

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

One way I can do this involves the substitution operator and a double /e flag. 我做到这一点的一种方法涉及替换运算符和double /e标志。 The first /e evaluates $1 on the replacement side and turns it into $foo . 第一个/e在替换端求值$1 ,并将其转换为$foo The second /e starts with $foo and replaces it with its value. 第二个/e$foo开头,并将其替换为它的值。 $foo , then, turns into 'Fred', and that's finally what's left in the string: 然后, $foo变成'Fred',最后就是字符串中剩下的:

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

The /e will also silently ignore violations of strict, replacing undefined variable names with the empty string. /e还将静默忽略违反严格的行为,用空字符串替换未定义的变量名。 Since I'm using the /e flag (twice even!), I have all of the same security problems I have with eval in its string form. 由于我正在使用/e标志(甚至两次!),因此我在字符串形式的eval中遇到了同样的安全问题。 If there's something odd in $foo , perhaps something like @{[ system "rm -rf /" ]} , then I could get myself in trouble. 如果$foo有些奇怪的东西,例如@{[ system "rm -rf /" ]} ,那么我可能会遇到麻烦。

To get around the security problem, I could also pull the values from a hash instead of evaluating variable names. 为了解决安全问题,我还可以从哈希中提取值,而不是评估变量名。 Using a single /e , I can check the hash to ensure the value exists, and if it doesn't, I can replace the missing value with a marker, in this case ??? 使用单个/e ,我可以检查哈希值以确保该值存在,如果不存在,则可以用标记替换丢失的值,在这种情况下??? to signal that I missed something: 表示我错过了一些东西:

  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; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM