Perl推送功能的奇怪行为

时间:2014-11-18 22:42:24

标签: arrays perl

我正在编写专用的ICS(iCalendar文件)解析器。

我将数组传递给子程序。除$notdates之外的所有变量都是单个值,这是逗号分隔的日期列表。

@entryl = ($dtstart, $dtend, $attendee, $lastmod, $uid, $notdates);
&entrytoarray(@entryl);

sub entrytoarray {

  # print Dumper @_;
  my $shiftdur = (&stamptoepoc($_[1]) - &stamptoepoc($_[0])) / 60 / 60;
  my $attendee = $_[2];
  my $deleted  = $_[5];
  $attendee =~ /ATTENDEE;USER-KEY=([^;]*);CN=([^;]*);.*:(.*)/;

  my %ehash = (
    "STARTDATE"   , &stamptodate($_[0]),
    "ENDDATE"     , &stamptodate($_[1]),
    "STARTSTAMP"  , $_[0],
    "ENDSTAMP"    , $_[1],
    "USERKEY"     , $1,
    "CN"          , $2,
    "EMAIL"       , $3,
    "LASTMOD"     , $_[3],
    "UID"         , $_[4],
    "DURATION"    , $shiftdur
  );

  # Only keep current data
  my $fdays = 4;
  my $tdays = 7;

  chomp(my $curstamp = `TZ="UTC" date -d "$fdays days" +"%Y%m%d%H%M00"`);
  chomp(my $stpstamp = `TZ="UTC" date -d "$tdays days" +"%Y%m%d%H%M00"`);

  if (($_[0] > $curstamp) && ($_[1] < $stpstamp)) {

    if (defined($deleted)) {

      my @deleted = split /,/, $deleted;

      foreach (@deleted) {
        if ($_ ne $_[0]) {
          push(@entry, \%ehash);
        }
      }
    }
    else {
      push(@entry, \%ehash);
    }
  }

  print Dumper @entry;

这大部分都符合预期:

$VAR1 = {
          'DURATION' => '5',
          'STARTSTAMP' => '20141122230000',
          'UID' => '20141114T010539Z--1092363482',
          'LASTMOD' => '20141118214419',
          'STARTDATE' => '2014-11-22 23:00:00',
          'EMAIL' => 'xxxxxxxxxxxxx',
          'ENDDATE' => '2014-11-23 04:00:00',
          'CN' => 'xxxxxxxxxxx',
          'ENDSTAMP' => '20141123040000',
          'KEY' => 'xxxxxxxxxxxxxxxxxx'
        };
$VAR2 = {
          'EMAIL' => 'xxxxxxxxxxxxx',
          'ENDDATE' => '2014-11-23 23:00:00',
          'ENDSTAMP' => '20141123230000',
          'KEY' => 'xxxxxxxxxxx',
          'CN' => 'xxxxxxxxxxxxxx',
          'STARTDATE' => '2014-11-23 19:00:00',
          'LASTMOD' => '20141118205901',
          'UID' => '20141114T010456Z--1092363482',
          'DURATION' => '4',
          'STARTSTAMP' => '20141123190000'
        };
$VAR3 = $VAR2;

$ VAR3 = $ VAR2来自哪里?

2 个答案:

答案 0 :(得分:1)

我猜这部分是罪魁祸首:

  foreach (@deleted) {
    if ($_ ne $_[0]) {
      push(@entry, \%ehash);
    }
  }

如果数组中有多个值,则if语句可以为真两次,因此将值推两次。除非这是想要的行为,否则我会确保只推送一个值。您可以使用grep代替:

if (grep { $_ ne $_[0] } @deleted) {
    push @entry, \%ehash;
}

请注意,这会取代foreach循环。

答案 1 :(得分:0)

您的数组@entry包含哈希引用。 Data::Dumper表示数组的第一个和第二个元素引用两个不同的哈希值,而第三个元素引用与第二个相同的哈希值。

您没有显示@entry的来源,但我希望所有三个元素都可以引用%ehash

问题在于,如果继续将%ehash的引用推送到@entry,它们都指向相同的数据项,并且不会记录哈希的中间状态。 / p>

除非你的意思是entrytoarray只推送一个%ehash副本(在这种情况下会出现一个我们看不到的单独问题),你需要修复它写作

push @entry, { %ehash }

复制哈希并返回对副本的引用,或者您可以在%ehash循环内声明并填充foreach ,这将在每次创建一个新哈希围绕循环。