perl - 使用子例程时出现错误“变量不会保持共享”
问题描述
我写了一个函数,这里是:
use strict;
use warnings;
use feature 'say';
use JSON;
use utf8;
sub process {
my %IDs = ( "User awx01 logged in." => 1001 );
my %levels = ( INFO => 4 );
my $data = do { local $/; <DATA> };
# read in all the data, even though it looks
my $decoded = decode_json( $data );
$decoded->{Message} = decode_json( $decoded->{Message} );
say rec2msg($decoded);
sub rec2msg {
my $r = shift;
$r->{Message}{message} =~ /(\w+) (\w+) (.+)/;
my($user,$msg) = ($2,"$1 $3");
my $ID = $IDs{$r->{Message}{message}};
my $level = $levels{$r->{Message}{level}};
my $out = "$r->{Message}{'@timestamp'} host CEF:0|OpenSource|AWX|7.0.0|$ID|$msg|$level|src=127.0.0.1 dst=$r->{MessageSourceAddress} duser=$user";
return $out;
}
}
__DATA__
{"MessageSourceAddress":"192.168.81.20","EventReceivedTime":"2020-02-06 11:55:14","SourceModuleName":"udp","SourceModuleType":"im_udp","SyslogFacilityValue":1,"SyslogFacility":"USER","SyslogSeverityValue":5,"SyslogSeverity":"NOTICE","SeverityValue":2,"Severity":"INFO","EventTime":"2020-02-06 11:55:14","Hostname":"192.168.81.20","Message":"{\"@timestamp\": \"2020-02-06T08:55:52.907Z\", \"message\": \"User awx01 logged in.\", \"host\": \"awxweb\", \"level\": \"INFO\", \"logger_name\": \"awx.api.generics\", \"stack_info\": null, \"type\": \"other\", \"cluster_host_id\": \"awx-contr-01\", \"tower_uuid\": \"333b4131-495f-4460-8e4b-890241a9d73d\"}"}
运行此代码后所需的输出是:
2021-02-06T08:55:52.907Z host CEF:0|OpenSource|AWX|7.0.0|1001|User logged in.|4|src=127.0.0.1 dst=192.168.81.20 duser=awx01
但是,当我运行此代码时,出现此错误:
变量“%IDs”不会在 /usr/libexec/nxlog/modules/extension/perl/event1.pl 第 25 行保持共享。变量“%levels”不会在 /usr/libexec/nxlog/modules/extension/ 保持共享perl/event1.pl 第 26 行。
我该如何解决?我真的需要它在一个功能中
我试过这个,但没有奏效:
use strict;
use warnings;
use feature 'say';
use JSON;
use utf8;
sub process {
my %IDs = ( "User awx01 logged in." => 1001 );
my %levels = ( INFO => 4 );
my $data = do { local $/; <DATA> };
# read in all the data, even though it looks
my $decoded = decode_json( $data );
$decoded->{Message} = decode_json( $decoded->{Message} );
say rec2msg($decoded);
local *rec2msg = sub {
my $r = shift;
$r->{Message}{message} =~ /(\w+) (\w+) (.+)/;
my($user,$msg) = ($2,"$1 $3");
my $ID = $IDs{$r->{Message}{message}};
my $level = $levels{$r->{Message}{level}};
my $out = "$r->{Message}{'@timestamp'} host CEF:0|OpenSource|AWX|7.0.0|$ID|$msg|$level|src=127.0.0.1 dst=$r->{MessageSourceAddress} duser=$user";
return $out;
}
return rec2msg();
}
__DATA__
{"MessageSourceAddress":"192.168.81.20","EventReceivedTime":"2020-02-06 11:55:14","SourceModuleName":"udp","SourceModuleType":"im_udp","SyslogFacilityValue":1,"SyslogFacility":"USER","SyslogSeverityValue":5,"SyslogSeverity":"NOTICE","SeverityValue":2,"Severity":"INFO","EventTime":"2020-02-06 11:55:14","Hostname":"192.168.81.20","Message":"{\"@timestamp\": \"2020-02-06T08:55:52.907Z\", \"message\": \"User awx01 logged in.\", \"host\": \"awxweb\", \"level\": \"INFO\", \"logger_name\": \"awx.api.generics\", \"stack_info\": null, \"type\": \"other\", \"cluster_host_id\": \"awx-contr-01\", \"tower_uuid\": \"333b4131-495f-4460-8e4b-890241a9d73d\"}"}
解决方案
使用嵌套的命名子程序有点不寻常。
该错误消息的文档提供了一些建议:
变量“%s”不会保持共享
(W 闭包)内部(嵌套)命名子例程正在引用在外部命名子例程中定义的词法变量。
当调用内部子程序时,它将看到外部子程序变量的值,就像它在第一次调用外部子程序之前和期间一样;在这种情况下,在对外部子例程的第一次调用完成后,内部子例程和外部子例程将不再共享该变量的公共值。换句话说,变量将不再被共享。
这个问题通常可以通过使用 sub {} 语法使内部子例程匿名来解决。当创建引用外部子例程中变量的内部匿名子时,它们会自动重新绑定到此类变量的当前值。
所以你可以听从这个建议,或者完全摆脱内部子程序。一眼看去,我看不出有什么真正的原因。
推荐阅读
- c - 为什么我的编译器在我使用 10^6 时不生成 N 个随机数,但对 10^5 没问题?
- python - 如何在python中将天气信息打印到控制台
- r - 我不明白 R 中的这个错误: In pt(-abs(tVal), fDF) : NaNs 产生
- php - 当我的表单在实时站点上提交时,PHP 表单没有发送电子邮件
- xamarin - 来自多个对象的 XAML ListSource 绑定
- android - 如何计算保持设备与地面平行的设备的角度
- machine-learning - 具有数据增强功能的 Keras(几乎)不会收敛
- javascript - 将图像发送到 S3 存储桶的 react-native 代码已停止发送网络请求
- javascript - 如何隐藏亚马逊 SES 收件人的电子邮件地址
- excel - 如何对报告进行排序,并向每个收件人发送一封电子邮件,其中包含所有关键值?