哈希遇到麻烦;第一次Perl问题

时间:2014-07-16 20:43:52

标签: perl hash

如果这个问题太模糊,我真的很抱歉;我会尽力尝试总结我的问题。这是我第一次搞乱Perl,我觉得我已接近它了。

我有一个哈希,它存储从Asterisk收到的呼叫信息。

每个调用都应该在哈希中有一个条目,密钥是唯一的ID(我知道这可能是不好的做法,但密钥将在脚本结束时销毁,所以我并不担心关于重复)。

当我从Asterisk获取时,我需要不断地将新数据附加到哈希元素,然后在某些时候将结果打印到TCP套接字。

这是我所拥有的。我的问题是我似乎无法将新数据附加到相同的哈希键。

请原谅我的业余爱好;任何关于格式化/最佳实践/任何事情的帮助表示赞赏!

use Asterisk::AMI;
use IO::Socket;

use strict;
use warnings;

use Data::Dumper;

my %call;

my $sock = new IO::Socket::INET(
  PeerAddr => '127.0.0.1',
  PeerPort => '1234',
  Proto    => 'tcp',
);

die "Could not create socket: $!\n" unless $sock;

my $astman = Asterisk::AMI->new(
  PeerAddr => '127.0.0.1',
  PeerPort => '5038',
  Username => 'user',
  Secret   => 'secret',
  Events   => 'on',
  Handlers => {
    #default    => \&eventhandler,
    Dial       => \&ringcheck,
    Bridge     => \&bridgecheck,
    Newchannel => \&newchannel
  }
);

die "Unable to connect to asterisk" unless ($astman);

# Default event handler
sub eventhandler {
  my ($ami, $event) = @_;

  print 'Got Event: ', $event->{'Event'}, "\r\n";
}

sub newchannel {
  my ($ami, $event) = @_;

  if ($event->{'Context'} eq "from-trunk") {
    $call = $event->{'Uniqueid'} => {
      caller_name   => $event->{'CallerIDName'},
      caller_number => $event->{'CallerIDNum'},
      dnis          => $event->{'Exten'}
    };
  }
}

sub ringcheck {
  my ($ami, $event) = @_;

  if ($event->{'SubEvent'} eq "Begin") {
    $call = $event->{'UniqueID'} => {
      system_extension => $event->{'Dialstring'},
      dest_uniqueid    => $event->{'DestUniqueID'}
    };
    print $sock "R|", $call{ $event->{'UniqueID'} }{'caller_name'}, "|",
        $call{ $event->{'UniqueID'} }{'caller_number'},    "|",
        $call{ $event->{'UniqueID'} }{'system_extension'}, "||",
        $call{ $event->{'UniqueID'} }{'dnis'},             "\r\n";
  }
}

sub bridgecheck {
  my ($ami, $event) = @_;

  if ($event->{'Bridgestate'} eq "Link") {
    # Call has started
    print $sock "A|", $call{ $event->{'UniqueID'} }{'caller_name'}, "|",
        $call{ $event->{'UniqueID'} }{'caller_number'},    "|",
        $call{ $event->{'UniqueID'} }{'system_extension'}, "||",
        $call{ $event->{'UniqueID'} }{'dnis'},             "\r\n";
  }
  elsif ($event->{'Bridgestate'} eq "Unlink") {
    # Call has ended
  }
}

EV::loop

要清楚,问题是我应该如何在ringcheck子例程中将新数据附加到%call子例程中创建的newchannel哈希?

2 个答案:

答案 0 :(得分:4)

由于您没有声明$call,因此您必须收到来自use strict的错误消息。如果你告诉我们,那会有很大的帮助。

  • 请使用最小缩进:通常使用四个或更少的空格,我使用两个。大缩进使代码难以遵循

  • 即使在Windows上,也不要使用"\r\n"终止输出行。 Perl处理所有这些,你应该在任何平台上打印"\n"换行

  • 哈希%call是与标量$call完全独立的变量,因此分配给$call根本不会影响您的哈希值。如果strict到位,您会看到错误,因为$call尚未定义

  • 要分配给哈希元素,请使用$hash{$key}。可以把它想象成一个数组元素,但是哈希元素不是整数,而是用字符串索引。如果要将常量用作散列键,则可以省略引号,因此$call{'caller_name'}$call{caller_name}

  • 相同
  • 现在只看ringcheck,如果将$event->{UniqueID}的值复制到标量变量而不是使用相同的哈希,它会使您的代码更简洁,更容易理解元素无处不在。您可以使用哈希引用$call{$unique_id}

  • 执行相同的操作

我已将您的代码更改为可能有效的内容,或者至少可以帮助您。我使用printf将格式与数据分开,使其更具可读性。

sub ringcheck {
  my ($ami, $event) = @_;

  if ($event->{SubEvent} eq 'Begin') {

    my $unique_id = $event->{UniqueID};
    my $this_call = $call{$unique_id};

    $this_call->{system_extension} = $event->{Dialstring};
    $this_call->{dest_uniqueid}    = $event->{DestUniqueID};

    printf $sock "R|%s|%s|%s||%s\n",
        $this_call->{caller_name},
        $this_call->{caller_number},
        $this_call->{system_extension},
        $this_call->{dnis};
  }
}

答案 1 :(得分:1)

您使用错误的运算符进行分配。 =>,的同义词,其附加效果是引用其左侧操作数(除非它是变量。)

我对Asterisk一无所知,但你可能想要:

$event->{'UniqueID'} = {
      system_extension => $event->{'Dialstring'},
      dest_uniqueid => $event->{'DestUniqueID'}
};

我不确定你在$call尝试做什么。