簡體   English   中英

如何在Perl中打印數組的數組-參考變量

[英]How to print the array of arrays in perl - reference variable

#! /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,大小和最后訪問時間。 它不打印任何值,

 for(@$array_ref){
  print "@$array_ref[$i]\n";
  $i++;
 }
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_ @印記和/或下標與[...]運營商清楚地表明,這是數組。

  • $ret_mode & 0777 –結果應為$ret_mode本身: 07770b111111111 即,這將刪除除最后9位之外的所有位-您無需擔心左側是否還有更多位。

  • $last_mod = scalar(localtime($info->mtime)); –由於標量分配, localtime時間已在標量上下文中執行。 無需對此進行明確說明。

  • my $index = 0; ... for (...) { $array[$index] = ...; $index++ } my $index = 0; ... for (...) { $array[$index] = ...; $index++ } 請不要 只需使用pushfor (...) { push @array, ... } 除非必須,否則不要自己維護索引。

  • $ret_mode = 0; 為什么? 您還是要在下一次迭代中分配一個新值。 請注意,您應該在循環中聲明此變量(請參見我關於嚴格范圍的觀點),這將在每次迭代中創建一個新變量,從而使此變量變得更加無用。

  • my $array_ref = \\@array_arrays; .. @$array_ref[$i] my $array_ref = \\@array_arrays; .. @$array_ref[$i] 這不是倒退嗎? $array_arrays[$i]也可以。 請注意,在您取消投票時, @可能是錯誤的符號。 您的意思是$$array_ref[$i]

讓我們嘗試一些不同的東西。

首先,對於引用的數組和哈希,使用->有一個不錯的語法。 在這里,我將結交很多人。 我將對%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};
    }
}

下一步是學習面向對象的Perl 面向對象的Perl使用了這些類型的引用,但是將大大簡化這些引用的處理,因此您可以減少編程錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM