我的代码如下:
use strict;
my $store = 'Media Markt';
my $sentence = "I visited [store]";
# Replace characters "[" and "]"
$sentence =~ s/\[/\$/g;
$sentence =~ s/\]//g;
print $sentence;
我在屏幕上看到了以下内容:
我参观了$ store
有可能看到以下内容吗?我想看看$ store的价值:
我访问了Media Markt
答案 0 :(得分:3)
您似乎在考虑使用字符串'store'
来构建变量名称$store
。这涉及到symbolic references的主题,你do not want to去了那里。
执行所需操作的一种方法是构建将此类字符串与相应变量相关联的哈希。然后捕获句子中括号内的字符串并用它们的哈希值替换它们
use warnings;
use strict;
my $store = 'Media Markt';
my $time = 'morning';
my %repl = ( store => $store, time => $time );
my $sentence = "I visited [store] in the [time]";
$sentence =~ s/\[ ([^]]+) \]/$repl{$1}/gex;
print "$sentence\n";
这会打印行I visited Media Markt in the morning
正则表达式使用negated character class [ ]
(除[^]]
之外的任何字符),]
之间的任何内容捕获任何内容,匹配一次或多次({{1} }})。然后用散列中的值替换它,使用+
来评估替换方作为表达式。由于括号也匹配,最终会被删除。 /e
允许内部空间,以便可读。
对于括号中的每个字符串,哈希中必须有一个键值对,否则您将收到警告。为了解释这一点,我们可以提供另一种选择
/x
defined-or
operator($sentence =~ s{\[ ([^]+) \]}{$repl{$1}//"[$1]"}gex;
)如果//
返回"[$1]"
(哈希中没有键$repl{$1}
,或者它有undef
,则会返回$1
undef
值)。因此,没有散列对的字符串不变。我将分隔符更改为s{}{}
,以便可以在内部使用//
。
这不允许嵌套(如[store [name]]
),不处理多行字符串,还有其他限制。但它应该适用于合理的案例。
答案 1 :(得分:2)
正如我在Perl程序员Facebook小组中所说的那样,这与Perl FAQ中的答案非常相似。
How can I expand variables in text strings?
如果您可以避免它,请不要,或者如果您可以使用模板系统,例如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
也会默默地忽略违反strict的行为,用空字符串替换未定义的变量名。由于我使用/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;
实际(但真的不推荐 - 出于上述常见问题解答中解释的原因)回答您的问题是:
$sentence =~ s/\[(\w+)]/'$' . $1/ee;