perl - 标量上的实验键现在被禁止警告

标签 perl

这不是我的代码,但似乎适用于旧版本的 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/

相关文章:

regex - Perl 正则表达式多重匹配

Perl LWP::useragent 捕获服务器响应 header

regex - 反向正则表达式搜索

perl - 在 Perl 中写入文件

arrays - 我将如何使用散列切片来初始化存储在数据结构中的散列?

regex - Perl:无法从文件中获取正确的匹配项

regex - 精通正则表达式书中的 Perl 替换示例对我不起作用

perl - 通过脚本识别静态库之间的循环依赖

performance - 如何在 Perl 中使用异步编程?

perl - 将 Moose 别名与 MooseX::Constructor::AllErrors 一起使用