2013-08-18 40 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使用這些類型的引用,但會大大簡化對這些引用的處理,所以你減少了編程錯誤。