映射奇怪的行为

时间:2014-03-14 11:02:36

标签: regex perl hash

我有一个如下的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值。有人能帮帮我吗?

1 个答案:

答案 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'),因为每个密钥只能出现一次。