【问题标题】:Map strange behaviour映射奇怪的行为
【发布时间】:2014-04-19 15:19:18
【问题描述】:

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

【问题讨论】:

  • 请显示命令输出的示例

标签: regex perl hash


【解决方案1】:

好吧,您必须考虑当正则表达式 匹配并且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'),因为每个键只能出现一次。

【讨论】:

  • 我不明白你对["", "hello", "bye", ""] 的期望。如果正则表达式匹配,则返回 ('hello' => 'bye');如果失败,则返回 ("")。除非你的意思是map 的结果,如果@dbnode_versions 有三个元素,其中只有第二个匹配?
  • @Borodin 输出["", "hello", "bye", ""] 是上面代码的实际输出,与["hello", "bye"] 形成对比。我使用了一个简化的示例来保持它的可重复性并避免问题中的正则表达式过长。
  • 好的明白了。谢谢。
猜你喜欢
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 2015-03-25
  • 2023-03-17
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多