2013-08-18 38 views
1
#! /usr/bin/perl 
use strict; 
use warnings; 
use File::stat; 

my $file_name = 0; 
my $info = 0; 
my $ret_mode = 0; 
my $size; 
my $last_mod; 
my @array_file; 
my $index = 0; 
my @array_mode; 
my @array_size; 
my @array_last_mod; 
foreach(@ARGV){ 
    $file_name = $_; 
    $info = stat($file_name); 
    $size = $info->size; 
    $last_mod = scalar(localtime($info->mtime)); 
    $ret_mode = $info->mode; 
    $ret_mode = $ret_mode & 0777; 
    $array_file[$index] = ($file_name); 
    $array_mode[$index] = ($ret_mode); 
    $array_size[$index] = ($size); 
    $array_last_mod[$index] = ($last_mod); 
    $ret_mode = 0; 
    $index++; 
} 
my @array_arrays = (@array_file, @array_mode, @array_size, @array_last_mod); 
my $array_ref = \@array_arrays; 
my $i = 0; 
for(@$array_ref){ 
    print "@$array_ref[$i]\n"; 
    $i++; 
} 

我已经创建了一个数组数组,我想从创建的数组数组中打印文件名,mmode,大小和最后访问时间。它不打印任何值与,如何在perl中打印数组的阵列 - 参考变量

for(@$array_ref){ 
    print "@$array_ref[$i]\n"; 
    $i++; 
} 
+1

查看perlLOL - [perl列表中的列表]的官方文档(http://perldoc.perl.org/perllol.html) –

回答

5
my @array_arrays = (@array_file, @array_mode, @array_size, @array_last_mod); 

此语句不创建一个数组的数组。相反,它将各种阵列变平成一个大的扁平列表,然后将其分配给@array_arrays。你想分配数组引用。获得这些与参考操作\

my @array_arrays = (\@array_file, \@array_mode, \@array_size, \@array_last_mod); 

或使用快捷

my @array_arrays = \(@array_file, @array_mode, @array_size, @array_last_mod); 

即使是这样,你的最后foreach -loop是错误的。你可能的意思是

for my $i (0 .. $#{ $array_arrays[0] }) { 
    for my $aref (@array_arrays) { 
    print $aref->[$i], "\n"; 
    } 
} 

或类似的东西。


您的代码风格可以改进。

  • 请不要在上面声明所有变量。尽可能在最严格的范围内声明它们。尝试在初始化时声明它们,例如

    for my $file_name (@ARGV) { 
        my $info = stat($file_name); 
        my size = $info->size; 
        ... 
    } 
    
  • 不要array_前缀您数组名称。 @ sigil和/或[...]运算符的下标清楚地表明这些是数组。

  • $ret_mode & 0777 - 结果应该是$ret_mode本身:07770b111111111。即这会除去最后9位以外的所有内容 - 你不会在意是否还有更多内容。

  • $last_mod = scalar(localtime($info->mtime)); - 由于标量分配,localtime已在标量上下文中执行。没有必要明确这一点。

  • my $index = 0; ... for (...) { $array[$index] = ...; $index++ }。请不要。只需使用pushfor (...) { push @array, ... }。除非必须,否则不要自行维护指数。

  • $ret_mode = 0;为什么?无论如何,你在下一次迭代期间分配一个新值。请注意,您应该在循环内声明这个变量(请参阅我关于紧凑范围的观点),这会在每次迭代中创建一个新变量,使其变得更加无用。

  • my $array_ref = \@array_arrays; .. @$array_ref[$i]。这是不是有点倒退? $array_arrays[$i]也可以。请注意,在您的防御中,@可能是错误的印记。你的意思是$$array_ref[$i]

3

让我们尝试一些不同的东西。

首先,使用->作为参考数组和散列使用了很好的语法。在这里,我要制作一批人。我会做的%person哈希包含所有的人的信息:现在

my %person; 
my $person{NAME} = "Bob"; 
my $person{JOB} = "Programmer"; 
my $person{PHONE} = "555-1234"; 

,我就会把它变成一个数组:

my @array 
my $array[0] = \%person; 

我可以引用人阵这种方式:

print ${$array[0]}{NAME} . "\n"; #Prints Bob 
print ${$array[0]}{JOB} . "\n"; #Prints Porgrammer 

但是,Perl中给了我一个很好的清洁方法来做到这一点:

print $array[0]->{NAME} . "\n"; #Prints Bob 
print $array[0]->{JOB} . "\n"; #Prints Progammer 

事实上,我可以一起跳过散列。在这里,我将Jill添加到我的阵列中:

$array[1]->{NAME} = "Jill"; 
$array[1]->{JOB} = "DBA"; 
$array[1]->{PHONE} = "555-5555"; 

您可以看到,这是一种使用引用的简单方法。更容易看到发生了什么并且需要更少的代码行。

你可以参考一个数组的数组是这样的:

$myarray[1]->[3] = 42; 

或有存储数组中的哈希。在这个时代,谁拥有只有一个电话号码?:

$person[1]->{PHONE}->[0] = "555-4567"; 
$person[1]->{PHONE}->[1] = "555-4444"; 

或者,使它更加复杂,我们可以有一个数组的哈希散列:

$person[1]->{PHONE}->{CELL}->[0] = "555-1111"; 
$person[1]->{PHONE}->{CELL}->[1] = "555-2222"; 
$person[1]->{PHONE}->{HOME}->[0] = "555-3333"; 
$person[1]->{PHONE}->{JOB}->[0] = "555-4444"; 
$person[1]->{PHONE}->{JOB}->[1] = "555-5555"; 

使用这个语法将真正帮助清理大量的代码。您不必将信息存储到仅用于进行引用的单个结构中。相反,您可以按照自己想要的方式简单设置结构,而无需中间步骤。

我们您的问题:你试图将有关文件的大量信息存储到一个系列阵列。你所希望的是$array_mode[1]$array_file[1]一起,你必须保持所有这些阵列同步。这是一个痛苦,它很复杂。

使用引用的全部目的是消除对多个变量的这种需要。如果你要使用引用,为什么不把你的整个文件结构存储到一个单一的数组中。

你真正想要的是一个哈希引用数组。并且,该哈希引用将基于您的文件属性进行键控。这里是你的代码重构成使用哈希引用数组。我甚至懒得去检查其余部分。例如,我不知道你的本地时间的事情将如何工作:

use strict; 
use warnings; 
use feature qw(say); 
use File::stat; 

my @files; 
for my $file (@ARGV) { 
    my $info = stat($file); 
    my $file = {};  #This will be a reference to a hash 
    $file->{NAME} = $file; 
    $file->{SIZE} = $info->size; 
    $file->{RET_MODE} = $info->mode & 0777; 
    $file->{LAST_MOD} = localtime $info->mtime; #Does this work?  
    push @files, $file #Pushes the hash reference onto the array 
} 

这是更短,更干净。另外,您知道$files[0]->{NAME}$files[1]->{SIZE}一起使用,并且如果您从数组中删除$files[0],或者将其转移到另一个变量,则该文件的所有属性都会合并在一起。

这里是你如何把它打印出来:

for my $file (@files) { 
    say "File Name: " . $file->{NAME}; 
    say "File Size: " . $file->{SIZE}; 
    say "Last Modified: " . $file->{LAST_MOD}; 
    say "File Mode: " . $file->{RET_MODE}; 
} 

简单易做。


不过,我认为你真正想要的是散列一个哈希。让你的文件名是关键,你的主要哈希,让{SIZE}{LAST_MOD}{RET_MODE}是关键的子散:

my %files = {}; #This is a hash of hashes 
for my $file_name (@ARGV) { 
    my $info = stat($file); 
    $files{$file_name}->{SIZE} = $info->size; 
    $files{$file_name}->{RET_MODE} = $info->mode & 0777; 
    $files{$file_name}->{LAST_MOD} = localtime $info->mtime; #Does this work?  
} 

现在,如果有人问,“当被foo.txt最后修改? “,你可以说:

say "File 'foo.txt' was last modified on " . $file{foo.txt}->{LAST_MOD}; 

,并打印出你的整个结构:

for my $file_name (sort keys %files) { 
    say "File: $file_name"; 
    for my attribute (sort keys %{ $file_name }) { 
     say " $attribute: " . $files{$file_name}->{$attribute}; 
    } 
} 

下一步是了解Object Oriented Perl!面向对象的Perl使用这些类型的引用,但会大大简化对这些引用的处理,所以你减少了编程错误。