[英]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 )。
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;
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
orprintf
: 您甚至可以使用sprintf
或printf
完成工作: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 witheval
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.