[英]Passing an array into Perl subroutine
我有一個子例程,該例程應將數組作為輸入,將其制成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套接字,而其他一些數據則通過POST發送到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
第一個問題,您將從何處獲得要傳遞給子例程的數組? 我問是因為您的示例數組實際上是數組引用。
那是:
@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-> {'gravityfree'}實際上已經是數組引用,我不確定為什么它允許您使用$ this_call-> {'gravityfree'} [INDEX]處理數組元素,所以也許有人比我可以啟發我們所有人。 我將注意到,引用數組的正確方法如下:
\@{$this_call->{'gravityfree'}}
無論如何,您只需將引用傳遞給子例程,而無需創建引用。 那是:
send_http($this_call->{'gravityfree'});
現在,在子例程中,您有了數組引用。 您正在正確讀取子例程參數,但是您需要在foreach循環中取消引用該引用。 像這樣:
foreach my $v ( @$http ) {
# ... loop body
}
這有意義嗎? 如果有任何不清楚的地方(或不起作用!),請通知我。
因此,在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
我不確定您要做什么,但一切都取決於您如何將數組傳遞給子例程。 您有兩種選擇,可以將其作為數組傳遞:
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)
要將其視為數組,您需要取消引用它才能指向它所指向的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.