将数组传递给Perl子例程

时间:2014-09-26 00:39:22

标签: arrays perl

我有一个子程序,应该将数组作为输入,将其转换为CSV,然后将其发布到URL。这是我到目前为止所得到的:

示例数组:

[   2823383062, 1411691539,   1411691541,        'outgoing',
    'SIP/fr',   'user@2000',  '2000',            'SIP/2000-000000a2',
    undef,      '6125551234', 'SIP/fr-000000a3', undef,
    undef,      8,            'Answered',        2,
    1,          'nada'
];

子程序:

sub send_http {
    my @http = @_;
    my $h    = LWP::UserAgent->new;
    $h->timeout(15);
    $h->agent(undef);

    my $testkey = "1234";
    my $apikey  = "4567";

    my $posting;
    foreach my $v ( \@http ) {
        if ( defined $v ) {
            $posting = join( ',', $posting, $v );
        } else {
            $posting = join( ',', $posting, "" );
        }
    }

    my $api_response = $h->post( 'http://url.com/v1/post.cfm',
        [ key => $testkey, method => 'pushCalls', rawdata => $posting ] );
}

原谅我所做的所有可怕的事情;这是我第一次使用Perl,而我还在学习各种各样的东西。我的问题是我似乎无法通过第一个数组变量声明(@http)从数组中获取值。我已经阅读了有关获取数组引用的内容,但我不确定在何处/如何执行此操作。任何帮助表示赞赏。

编辑: 这是整个脚本。它确实(或应该)有两件事;将一些数据字符串发送到TCP套接字,并将其他一些数据发送到URL。谢谢大家的帮助。

#!/usr/bin/perl
use EV;
use Asterisk::AMI;
use Net::Telnet;
use HTTP::Request::Common;
use LWP::UserAgent;
use strict;
use warnings;
use Data::Dumper;

my %call;

my $t = new Net::Telnet (
  Timeout => 10,
  Port => '1234',
  Telnetmode => 1
);

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

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

sub send_pos {
  my ($pos_string,$telnet) = @_;

  $telnet->open('127.0.0.1');
  printf $t $pos_string;
  $telnet->close()
}

sub send_http {
  my $http = shift; #@_;
  my $h = LWP::UserAgent->new;
    $h->timeout(15);
    $h->agent(undef);

  my $testkey = "1234";
  my $apikey = "5678";

  my $posting;
  foreach my $v ( @http ) {
    if ( defined $v ) {
      $posting = join(',', $posting,$v);
    } else {
      $posting = join(',', $posting,"");
    }
  }

  my $api_response = $h->post( 'http://url.com/v1/post.cfm',[key => $testkey,method => 'pushCalls',rawdata => $posting]);
}

sub eventhandler { 
  #   Default event handler, not used
  my ($ami, $event) = @_; 
  print 'Got Event: ',$event->{'Event'},"\r\n";
}

sub newchannel {
  my ($ami, $event) = @_;
  my $unique_id = $event->{'Uniqueid'};

  if ( not exists $call{$unique_id} ) {
    my $this_call = $call{$unique_id};

  if ( (not defined $this_call->{'gravityfree'}[3]) ) {# || ($this_call->{'gravityfree'}[3] !~ /incoming|outgoing/) ) {
    if ( $event->{'Context'} =~ /from-trunk/ ) {
      #   Call is inbound
      $this_call->{'caller_name'} = $event->{'CallerIDName'};
      $this_call->{'caller_number'} = substr $event->{'CallerIDNum'}, -10;
      $this_call->{'dnis'} = substr $event->{'Exten'}, -10;
      $this_call->{'status'} = "remote";
      $this_call->{'holdstart'} = time();

      # Data required for Gravity Free
      $this_call->{'gravityfree'}[0] = int($event->{'Uniqueid'})+int(time());
      $this_call->{'gravityfree'}[3] = "incoming";
      $this_call->{'gravityfree'}[5] = $event->{'CallerIDName'};
      $this_call->{'gravityfree'}[6] = substr $event->{'CallerIDNum'}, -10;
      $this_call->{'gravityfree'}[7] =  $event->{'Channel'};
      $this_call->{'gravityfree'}[11] = substr $event->{'Exten'}, -10; 

      #  Can't remember why this is here:
      $call{$unique_id} = $this_call;

    } elsif ( $event->{'Context'} =~ /from-internal/ ) {
      #   Call is outbound
      #   Separate from calls to stations
      if( length($event->{'CallerIDNum'}) < length($event->{'Exten'}) ) {
          $this_call->{'status'} = "remote";
          #   Data required for Gravity Free
          $this_call->{'gravityfree'}[0] = int($event->{'Uniqueid'})+int(time());
          $this_call->{'gravityfree'}[9] = substr $event->{'Exten'}, -10;
          $this_call->{'gravityfree'}[3] = "outgoing";
          $this_call->{'gravityfree'}[6] = $event->{'CallerIDNum'};
          $this_call->{'gravityfree'}[5] = $event->{'CallerIDName'};

          $call{$unique_id} = $this_call;
      } elsif ( length($event->{'CallerIDNum'}) == length($event->{'Exten'}) ) {
        #   Call is station to station
        $this_call->{'status'} = "station-to-station";
      }
    }
  }
}
}

sub newexten {
  my ($ami, $event) = @_;
  my $unique_id = $event->{'Uniqueid'};
  my $this_call = $call{$unique_id};

  #   Handles inbound calls only
  if ( defined $this_call->{'status'} && $this_call->{'status'} ne "station-to-station" ) {
    #   Call is not station to station
    #   Check if the DID has been defined
    if ( not defined $this_call->{'gravityfree'}[13] ) {
      if ( $event->{'Context'} eq 'ext-group' ) {
        # Data required for Gravity Free
        $this_call->{'gravityfree'}[13] = $event->{'Extension'};
      }
    }
  }
}

sub dialcheck {
  my ($ami, $event) = @_;
  my $unique_id = $event->{UniqueID};

  if ( exists $call{$unique_id} ) {
    my $this_call = $call{$unique_id};

    if ( defined $this_call->{'status'} && $this_call->{'status'} ne "station-to-station" ) {
      #   Call is not station to station
      if ( $event->{'SubEvent'} eq 'Begin' && $this_call->{'gravityfree'}[3] =~ "incoming" ) {
        #   Call is inbound
        $this_call->{'system_extension'} = $event->{'Dialstring'};
        $this_call->{'dest_uniqueid'}  = $event->{'DestUniqueID'};

        # Data required for Gravity Free
        $this_call->{'gravityfree'}[4] = $1 if $event->{'Channel'} =~ /(.+(?=\-\w+)).*/;

        #   Telnet data to Prodigy  
        my $sending = "R|$this_call->{'caller_name'}|$this_call->{'caller_number'}|$this_call->{'system_extension'}||$this_call->{'dnis'}|";
        send_pos($sending,$t);

        $this_call->{'status'}  = "ringing";
      } elsif ( $event->{SubEvent} eq 'Begin' && $this_call->{'gravityfree'}[3] =~ "outgoing" ) {
        #   Call is outbound
        #   Data required for Gravity Free
        $this_call->{'gravityfree'}[4] = $1 if $event->{'Destination'} =~ /(.+(?=\-\w+)).*/;
        $this_call->{'gravityfree'}[10] = $event->{'Destination'};
        $this_call->{'gravityfree'}[7] = $event->{'Channel'};
      }
    }
  }
}

sub outring {
  my ($ami, $event) = @_;
  my $unique_id = $event->{'Uniqueid'};
  my $this_call = $call{$unique_id};

  if ( defined $this_call->{'status'} && $this_call->{'status'} ne "station-to-station" ) {
    #   Call is not station to station  
    if ( not defined $this_call->{'holdstart'} && $this_call->{'gravityfree'}[3] eq "outgoing" ) {
      #   Call is outbound
      $this_call->{'holdstart'} = time();
    }
  }
}

sub bridgecheck {
  my ($ami, $event) = @_;
  my $unique_id = $event->{'Uniqueid1'};
  my $this_call = $call{$unique_id};

  if ( defined $this_call->{'status'} && $this_call->{'status'} ne "station-to-station" ) {
    #   Call is not station to station
    if ( $event->{'Bridgestate'} eq "Link" && length($event->{'CallerID2'}) <= 4 ) {
      #   Call is inbound
      $this_call->{'dest_uniqueid'}  = $event->{Uniqueid2};

      # Data required for Gravity Free
      $this_call->{'gravityfree'}[1] = time();
      $this_call->{'gravityfree'}[10] = $event->{Channel2};

      my $sending = "A|$this_call->{caller_name}|$this_call->{caller_number}|$event->{CallerID2}||$this_call->{dnis}|";
      send_pos($sending,$t);

      $this_call->{'status'}  = "answered";

    } elsif ( $event->{'Bridgestate'} eq "Link" && length($event->{'CallerID2'}) >= 4 ) {
      #   Call is outbound
        $this_call->{'gravityfree'}[1] = time();
        $this_call->{'gravityfree'}[13] = $this_call->{'gravityfree'}[1]-$this_call->{holdstart};
    }
  }
}


sub hangup {
  my ($ami, $event) = @_;
  my $unique_id = $event->{'Uniqueid'};
  my $this_call = $call{$unique_id};

  if ( defined $this_call->{'status'} && not defined $this_call->{'gravityfree'}[16] && $this_call->{'status'} ne "station-to-station" ) {
    #   Call is not station to station
    if ( $event->{'Cause-txt'} eq "Normal Clearing" ) {
      #   Call was hungup normally
      $this_call->{'dest_uniqueid'}  = $event->{Uniqueid};
      #   Call has ended, get date/time
      $this_call->{'gravityfree'}[2] = time();
      #   Mark call 'completed'
      $this_call->{'gravityfree'}[16] = 1;
      #   Set notes to nothing
      $this_call->{'gravityfree'}[17] = 'nada';

      if ( defined $this_call->{'gravityfree'}[3] && $this_call->{'gravityfree'}[3] eq "incoming") {
        #   Call was inbound
        if ( defined $this_call->{'gravityfree'}[1] ) {
          #   Call was answered
          $this_call->{'gravityfree'}[13] = $this_call->{'gravityfree'}[1]-$this_call->{holdstart};
          $this_call->{'gravityfree'}[14] = "Answered";
          $this_call->{'gravityfree'}[15] = $this_call->{'gravityfree'}[2]-$this_call->{'gravityfree'}[1];
          $this_call->{'gravityfree'}[8] = $event->{'ConnectedLineName'};
          $this_call->{'gravityfree'}[9] = substr $event->{'ConnectedLineNum'}, -10;

          #   POST data to gravity free
          send_http(\$this_call->{'gravityfree'});

        } else {
          #   Call was abandoned
          $this_call->{'gravityfree'}[14] = "Abandoned";
          $this_call->{'gravityfree'}[13] = $this_call->{'gravityfree'}[2]-$this_call->{holdstart};
          $this_call->{'gravityfree'}[15] = 0;

          #   POST data to gravity free
          send_http(\$this_call->{'gravityfree'});
        }

      } elsif ( defined $this_call->{'gravityfree'}[3] && $this_call->{'gravityfree'}[3] eq "outgoing" ) {
        #   Call is outbound
        if ( defined $this_call->{'gravityfree'}[1] ) {
          #   Call was bridged at some point
          $this_call->{'gravityfree'}[15] = $this_call->{'gravityfree'}[2]-$this_call->{'gravityfree'}[1];
          $this_call->{'gravityfree'}[14] = "Answered";

          #   POST data to gravity free
          send_http(\$this_call->{'gravityfree'});
        } else {
          #   Call was hung up before anyone answered
          $this_call->{'gravityfree'}[15] = 0;
          $this_call->{'gravityfree'}[14] = "Abandoned";
          $this_call->{'gravityfree'}[13] = $this_call->{'gravityfree'}[2]-$this_call->{holdstart};

          #   POST data to gravity free
          send_http(\$this_call->{'gravityfree'});
        }
      }
    }
  }
}

EV::loop

3 个答案:

答案 0 :(得分:1)

第一个问题,你在哪里获得你传入子程序的数组? 我问,因为你的示例数组实际上是一个数组引用。

那是:

@array = (1, 2, 3);  # This is an array
$ref   = [1, 2, 3];  # This is an array reference

如果要将数组引用传递给子例程,请将开头更改为:

sub send_http {
my $http = shift;

接下来,让我们考虑如何迭代数组的元素。这是正确的方法:

foreach my $element ( @array ) { 
  # do stuff ...
}

在数组上执行\ @时,实际上是在创建对数组的引用。因此,如果您确实将数组传递给子例程,则应将循环更改为以下内容:

foreach my $v ( @http ) {

但是,如果您决定将数组作为引用传递,则可以取消引用指针并迭代其元素,如下所示:

foreach my $v ( @$http ) {

希望这有帮助!

编辑:对于新上传的代码......

你非常接近,但我们有几个小问题:

$ this_call-&gt; {'gravityfree'}实际上已经是一个数组引用,我不确定为什么它允许你使用$ this_call-&gt; {'gravityfree'} [INDEX]来解决数组元素,所以或许比我更有知识的人可以启发我们所有人。我将注意到,尊重数组的正确方法如下:

\@{$this_call->{'gravityfree'}}

无论如何,您只需将引用传递给子例程,无需创建引用。那就是:

send_http($this_call->{'gravityfree'});

现在,在子例程内部,您有一个数组引用。您正在读取子例程参数,但需要在foreach循环中取消引用该引用。像这样:

foreach my $v ( @$http ) {
  # ... loop body
}

这有意义吗?如果有什么不清楚(或不工作!),请告诉我。

答案 1 :(得分:0)

因此,在你的send_http中,你收到的参数是array_ref,它是标量变量,所以当你使用它时,你需要取消引用正确的类型。

注意:方括号是array_reference

所以,请改变如下:

my $http = shift;

请将其用作:

foreach my $v ( @$http ) {

示例:

my $array_ref = [1,2,3];
print "Reference: ", $array_ref,"\n";
print "Array: ", @$array_ref,"\n";

输出:

Reference: ARRAY(0x7f8e1c004ee8)
Array: 123

答案 2 :(得分:0)

我不完全确定你要做什么,但一切都取决于你如何将数组传递给你的子程序。你有两个选择,要么把它作为数组传递:

send_http(@array)

或作为对数组的引用:

send_http(\@array)

正如其他人所说,你的数组已经是一个参考,因为你用方括号[ ]定义它。

您想要哪一个取决于您正在做什么,但语法不同。传递一个数组并遍历它:

sub send_http {
my @http = @_;
  foreach my $v (@http) {
      print "v is $v\n";
 }
}
my @aa=("cc","dd");
send_http(@aa);

要传递引用并遍历数组,它指向:

sub send_http {
 ## Remove the first value from the @_ array.
 my $http = shift @_;
 ## Dereference it to an array. You could also use @{$http}
 foreach my $v (@$http) {
      print "v is $v\n";
 }
}

my @aa=("cc","dd");
send_http(\@aa);

主要区别在于,当您使用send_http(\@aa);时,您传递的内容不是数组,因此您无法将其视为一个数组。它是对数组的引用。像

这样的东西
send_http(ARRAY(0x1d34030));

因此,@_的内容只是一个引用ARRAY(0x1d34030)。要将其视为数组,您需要取消引用它以获得它指向的内容。