这不是我的代码,但似乎适用于旧版本的 Perl。我得到:
Experimental keys on scalar is now forbidden at jdoodle.pl line 32. Type of arg 1 to keys must be hash or array (not hash element) at jdoodle.pl line 32, near "}) "
当我尝试运行该程序时出现错误。由于我不是程序员,我已尝试尽我所知更改哈希/标量语句。
use strict;
my $file = $ARGV[0] || die "You must supply a file to read.";
if (!open(FP, $file)) {
print STDERR "ERROR: Unable to open $file: $!\n";
exit(1);
}
my $data = join('', <FP>);
close(FP);
$data =~ s/\{\s*\}/{}/g;
$data =~ s/\/\*.*?\*\/\n*//g;
hash2sets(config2hash($data));
exit(0);
sub hash2sets {
my $config = shift;
my $start = shift || 'set';
if (ref($config) ne 'HASH') {
print STDERR "ERROR: '$config' is not a HASH at '$start'\n";
exit(1);
}
foreach my $key (sort(keys(%{$config}))) {
if (ref($config->{$key}) eq 'HASH') {
if (keys($config->{$key}) == 0) {
print "$start $key\n";
} else {
hash2sets($config->{$key}, "$start $key");
}
} elsif (ref($config->{$key}) eq 'ARRAY') {
foreach my $val (sort(@{$config->{$key}})) {
print "$start $key $val\n";
}
} else {
print "$start $key " . $config->{$key} . "\n";
}
}
}
sub config2hash {
my $config = shift;
my $pad = shift || '';
my (%hash);
while ($config =~ m/^$pad(\S+)\s+(".+?"|\S+ \{\}|\S+\s+\{.*?\n$pad\}|{.*?\n$pad\}|\S+)/gsm) {
my $tag = $1;
my $info = $2;
if ($info =~ m/^(\S+)\s+\{\n(\s*)(.*?)\n$pad\}/sm) {
my $name = $1;
$hash{$tag}{$name} = config2hash("$2$3", $2);
next;
} elsif ($info =~ m/^(\S+)\s+\{\}/sm) {
$hash{$tag}{$1} = {};
next;
}
if (ref($info) ne 'HASH' && $info =~ m/\{\n(\s*)(.*?)\n$pad\}/sm) {
$info = config2hash("$1$2", $1);
} elsif ($info eq '{}') {
$info = {};
}
if (!exists($hash{$tag})) {
$hash{$tag} = $info;
} else {
if (ref($hash{$tag}) ne 'ARRAY') {
$hash{$tag} = [$hash{$tag}];
}
push(@{$hash{$tag}}, $info);
}
}
return(\%hash);
}
它似乎适用于前几行,但随后输出不正确。我尝试进行一些调试来查看哈希值,但我不知道哪种模式现在不起作用:
Input:
firewall {
all-ping enable
broadcast-ping disable
group {
port-group CloudKey {
description "Unifi Cloudkey"
port 80
port 3478
port 11143
}
port-group VPN {
description "Sts vpn"
port 500
port 1701
port 50
port 4500
}
}
ipv6-name STS-VPN-6 {
default-action drop
enable-default-log
rule 1 {
action accept
state {
established enable
related enable
}
}
rule 2 {
action drop
log enable
state {
invalid enable
}
}
rule 100 {
action accept
log enable
protocol icmp
}
}
Output:
set firewall all-ping enable
set firewall broadcast-ping disable
set firewall group port-group CloudKey description "Unifi Cloudkey"
set firewall group port-group CloudKey port 11143
set firewall group port-group CloudKey port 3478
set firewall group port-group CloudKey port 80
set firewall group port-group VPN description "Sts vpn"
set firewall group port-group VPN port 1701
set firewall group port-group VPN port 4500
set firewall group port-group VPN port 50
set firewall group port-group VPN port 500
set firewall ip-src-route disable
set firewall ipv6-name STS-VPN-6 default-action drop
set firewall ipv6-name STS-VPN-6 enable-default-log rule
set firewall ipv6-name STS-VPN-6 } rule
set firewall ipv6-name STS-VPN-6 } rule
最佳答案
我在 Perl 版本 5.22 上收到警告,但在旧版本 5.16 上没有收到警告。
我使用 diagnostics 获得了有关该警告的更多信息:
perl -Mdiagnostics jdoodle.pl jdoodle.pl
keys on reference is experimental at ...
(S experimental::autoderef) keys with a scalar argument is experimental
and may change or be removed in a future Perl version. If you want to
take the risk of using this feature, simply disable this warning:
no warnings "experimental::autoderef";
如果我将以下内容添加到代码中,警告就会消失:
no warnings "experimental::autoderef";
但是,这感觉就像一个临时创可贴。我相信你可以改变:
if (keys($config->{$key}) == 0) {
至:
if (keys(%{ $config->{$key} }) == 0) {
这将取消引用哈希值。
关于perl - 标量上的实验键现在被禁止警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61923260/