Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays hashrefs问题的Perl数组_Arrays_Perl_Hashref - Fatal编程技术网

Arrays hashrefs问题的Perl数组

Arrays hashrefs问题的Perl数组,arrays,perl,hashref,Arrays,Perl,Hashref,我在我的项目中有: sub get_src_info($) { my $package = shift; my ($key,$value,$tail) =("","",""); my (@APT_INFO,$r); open APT, "apt-cache showsrc $package|"; while (<APT>){ chomp;

我在我的项目中有:

sub get_src_info($) {
        my $package = shift;
        my ($key,$value,$tail) =("","","");
        my (@APT_INFO,$r);

        open APT, "apt-cache showsrc $package|";

        while (<APT>){
                chomp;
                ($key,$value,$tail) = split /:/;
                if (defined ($key) && defined ($value)) {
                        $value =~ s/^\s+|\s+$//;
                        if (defined($tail)) {
                                $value = "$value:$tail";
                        }
                        if ( $key eq "Package" or $key eq "Version" ) {
                                $r->{$key} = $value;
                        }
                }
                if(/^$/) { push @APT_INFO,$r++; }
        }
        close APT;
        return @APT_INFO;
}
第61行是:
$r->{$key}=$value

我更喜欢修复代码,而不是让代码沉默,但不知道哪里出了问题/如何修复

另外,什么是正确的方法来推进一个指向下一个对象的引用?虽然它可以工作,但我觉得这里的
$r++
结构不正确


非常感谢。

您使用
$r
变量既作为哈希引用
$r->{$key}
,又作为数字
$r++
。将numify引用到ID,因此可以将其用作数字。但是,不能将非引用标量用作引用(引用不是指针)。为了说明这一点:

my $reference = { foo => 1 };
my $numified  = 0 + $reference;  # is now 163277181
say $numified->{foo};  # does not work under strict "refs"
# ${"163277181"}{foo} is equivalent: This looks for global variable %163277181
只要在新块开始时在
$r
中创建一个新引用,就可以解决这些问题。您还应该正确地确定其他变量的范围:不要使用全局变量,如
APT
,并在循环中声明
$key
等变量

另外,
$key
永远不能
undef
split
不会返回
undef
值),您不应该使用原型

我想下面的代码可以满足您的要求:

use autodie; # automatic error handling, e.g. for `open`

sub get_src_info {
  my ($package) = @_;
  my $info = {};
  my @apt_info;

  open my $fh, "-|", "apt", "showsrc", $package; # circumvent the shell for safety
  while (<$fh>) {
    chomp;
    unless (length) {
      push @apt_info, $info;
      $info = {};  # put a new reference into $info
      next;
    }
    my ($key, $value) = split /:/, $_, 2;  # limit number of fragments to 2
    next unless $key eq "Package" or $key eq "Version";
    s/^\s+//, s/\s+$// for $value;  # this trims at *both* ends
    $info->{$key} = $value;
  }

  return @apt_info;
}
使用autodie;#自动错误处理,例如“打开”`
子获取\u src\u信息{
我的($套餐)=@;
我的$info={};
我的@apt_信息;
打开我的$fh、“-|”、“apt”、“showsrc”、“$package;#为安全起见绕过外壳
而(){
咀嚼;
除非(长度){
推送@apt_info,$info;
$info={};#将新引用放入$info中
下一个
}
my($key,$value)=拆分/:/,$,2;#将片段数限制为2
下一步除非$key eq“包”或$key eq“版本”;
s/^\s+//,s/\s+$//表示$value;#这将在*两端修剪
$info->{$key}=$value;
}
返回@apt_info;
}
更多关于参考与指针的信息: 不能在内存安全语言中使用指针算法。Perl就是这样一种内存安全的语言。您可以使用的引用类似于C中的指针。它们也是类型化的(虽然是动态的),但是引用是自动计数的,因此引用的数据结构在不需要时被释放。垃圾收集和内存安全的支持者指出,错误更少(例如,double
free
)和生产率更高,尽管有些算法可能无法优雅地表达出来。默认情况下,大多数现代语言都是内存安全的


即使这是C,并且
$r++
将指向一个新地址,我也不得不问你:你不应该
malloc
新内存吗?内存分配在Perl中是隐式的。
$r={}
为我们提供了一个新的空哈希引用。如果使用词法变量(使用
my
),也会自动取消分配。

在您介绍的代码中,
$r
unde
或整数。然后,当您将
$value
分配给
$r->{$key}
时,尝试使用
$r
作为散列引用。所以,不要这样做。我不知道你所说的“提前引用以显示在下一个对象上”是什么意思。同样,我也不知道你所说的“提前引用以指向下一个对象”是什么意思。在Perl中,增量运算符应该只用于非引用标量。对不起,但我不明白您使用“$r++;”做了什么,因为显然$r是一个hashref,而不是一个简单的int。。。
use autodie; # automatic error handling, e.g. for `open`

sub get_src_info {
  my ($package) = @_;
  my $info = {};
  my @apt_info;

  open my $fh, "-|", "apt", "showsrc", $package; # circumvent the shell for safety
  while (<$fh>) {
    chomp;
    unless (length) {
      push @apt_info, $info;
      $info = {};  # put a new reference into $info
      next;
    }
    my ($key, $value) = split /:/, $_, 2;  # limit number of fragments to 2
    next unless $key eq "Package" or $key eq "Version";
    s/^\s+//, s/\s+$// for $value;  # this trims at *both* ends
    $info->{$key} = $value;
  }

  return @apt_info;
}