我有一个如下的map函数,它从unix命令生成的行数组中读取。
my %versions = map {
if (m/(?|(?:^Patch\s(?(?=description).*?(\w+)\sPATCH).*?(\d+(?:\.\d+)+).*)|(?:^(OPatch)\s(?=version).*?(\d+(\.\d+)+)))/)
{ 'hello' => 'bye'; }
} @dbnode_versions;
print Dumper(\%versions);
给出了
$VAR1 = {
'' => undef,
'hello' => 'bye',
'bye' => ''
};
我觉得非常奇怪,因为如果正则表达式为真,则只应添加hello和bye值。有人能帮帮我吗?
答案 0 :(得分:6)
好吧,你必须考虑当正则表达式没有匹配时会发生什么,if
为假。 if
会评估某个值,但您不应该依赖于语句的值。
特别是,if (cond) { expression }
大致相当于cond and expression
。这意味着如果正则表达式(我们的cond
)不匹配,我们将获得错误值。
use Data::Dump;
dd [map { /foo(bar)/ and (hello => 'bye') } qw/foo foobar bar/];
您的预期产量是多少?您可能已经想过["hello", "bye"]
。但实际上,我们得到了
["", "hello", "bye", ""]
因为""
表示失败时正则表达式匹配返回的假值。
如果您想在失败的情况下不返回任何内容,则应显式返回一个空列表:
map { /foo(bar)/ ? (hello => 'bye') : () } qw/foo foobar bar/
或使用grep
,它会过滤符合条件的元素的列表:
my %hash =
map { hello => 'bye' } # replace each matching element
grep { /foo(bar)/ } # filter for matching elements
qw/foo foobar bar/;
%hash
将()
或(hello => 'bye')
,因为每个密钥只能出现一次。