2015-01-01 80 views
1

我試圖通過使用foreach循環外部的索引鍵值從數據打印列。如何打印表格數據中的特定列

my @col; 
foreach(<DATA>){ 
    @x = split(' ',$_); 
@xz = ($x[0],$x[1],$x[2]) ; 
    #print "$x[0]\n"; This is working but i'm not expect this. 
push(@col,@xz); 
} 
print "$col[0]\n"; 
__DATA__ 
7  2  3 

3  2  8 

6  7  2 

我期望輸出

7 3 6 

我該怎麼辦呢?

回答

2
my @col; 
while (<DATA>) { 
    push @col, (split ' ')[0]; 
    # push @col, /(\S+)/; # split alternative 
} 
print "@col\n"; 

__DATA__ 
7  2  3 

3  2  8 

6  7  2 

輸出

7 3 6 
-1

你覺得我很親密。這是我做了什麼(編輯,以反映來自@Borodin評論):

use strict; 
use warnings; 

sub getColumn { 
    my ($data, $col) = @_; 
    my @output = map $_->[$col], @{$data}; 
    return @output; 
} 

my @data; 
while (<DATA>){ 
    push(@data, [split(' ',$_)]); 
} 
print join(' ', getColumn(\@data, 0), "\n"); 
print join(' ', getColumn(\@data, 1), "\n"); 
print join(' ', getColumn(\@data, 2), "\n"); 

__DATA__ 
7  2  3 
3  2  8 
6  7  2 

這子程序getColumn應該讓您檢索任意列。當我與您的數據運行它,我得到這個輸出:

7 3 6 
2 2 7 
3 8 2 
+0

@RonBergin良好的漁獲,謝謝! – rchang

+1

我也會清理那些打印語句。如果您不介意,我將使用該更新修改您的帖子。 –

+1

你的程序不會像現在這樣編譯,因爲沒有沒有'use特性'say''或'use 5.010'或類似的'say'。你真的應該''嚴格使用'並'使用警告'以及。爲什麼你使用'for'而不是'while'來讀取文件?而'getColumn'子例程是不必要的。如果你真的想保留它,那麼它可以寫成'map $ _-> [$ col],@ {$ data}'。 – Borodin

3

始終使用use strict;use warnings;

你有幾個問題:

push(@col, @xz); 

在這種情況下,你@xz陣列丟失您的信息。這個循環之後,你最終得到一個數組,看起來像這樣:

@col = (7, 2, 3, 3, 2, 8, 6, 7, 2); 

所以,當你打印:

print "$col[0]\n"; 

你得到的是零個元素:7

我們可以通過使用reference保存數據的結構:

#! /usr/bin/env perl 
# 
    use strict;    # Lets you know when you misspell variable names 
    use warnings;   # Warns of issues (using undefined variables 

    use feature qw(say); 
    use Data::Dumper; 

    my @columns; 
    for my $data (<DATA>) { 
     my @data_list = split /\s+/, $data; 
     push @columns, \@data_list; 
} 

say Dumper \@columns; 

__DATA__ 
7  2  3 
3  2  8 
6  7  2 

這裏你可以看到我已經包括Data::Dumper打印出的@columns結構:

$VAR1 = [ 
      [ 
      '7', 
      '2', 
      '3' 
      ], 
      [ 
      '3', 
      '2', 
      '8' 
      ], 
      [ 
      '6', 
      '7', 
      '2' 
      ] 
     ]; 

正如你所看到的,@columns陣列中的每個條目現在是另一個數組。但是,打印出$columns[0]數組引用不會打印您想要的內容。相反,它會打印零數組引用:7,2,3,而不是零每個數組引用的元素:7,3,6,

爲了做到這一點,我們需要一個子程序將去通過@columns並打印出每個數組的第零個條目。在這裏我要創建一個名爲fetch_index子程序,將取傳遞的數組的傳遞指數:

#! /usr/bin/env perl 
# 
    use strict;    # Lets you know when you misspell variable names 
    use warnings;   # Warns of issues (using undefined variables 

    use feature qw(say); 
    use Data::Dumper; 

    my @columns; 
    for my $data (<DATA>) { 
     my @data_list = split /\s*/, $data; 
     push @columns, \@data_list; 
} 

say join ", ", fetch_index(0, @columns); 

sub fetch_index { 
    my $entry = shift;  #Entry you want from all arrays 
    my @array = @_; 

    my @values; 

    for my $array_ref (@array) { 
     push @values, ${array_ref}->[$entry]; 
    } 
    return @values; 
} 

__DATA__ 
7  2  3 
3  2  8 
6  7  2 

子程序僅僅通過每個數組引用我已經保存在我的數組去,並從提取了$entry值數組引用。我將這些推入我的@values陣列並返回。

+1

出錯的最佳解釋以及如何正確使用。 –

+0

關於'split()','\ s +'是(幾乎?)總是比'\ s *'要好https://eval.in/238890 –

+1

@Сухой27Darn。你是對的。我通常做'/ \ s + /'。 –

0

一旦你在這裏吸收了關於匿名數組和參考資料的信息,你就可以開始玩得開心了。 例如你經常可以得到一個襯墊的工作方式:

perl -nE 'say [split]->[1] ' col_data.txt 

將環(-n創建一個隱含while(){}環)通過數據col_data.txtsplit話題變量($_)創造了一系列從每個匿名數組行,然後打印第二個元素或「列」。

您可以使用autosplit command line option (-a)將每行分成一個名爲@F(助記符:「F」代表「字段」)的數組。在perl更高版本中,-a意味着隱含while環路(-n):

perl -anE 'say $F[1] ' col_data.txt 

將是前一命令的等效 - 印刷第二柱:

輸出

2 
2 
7 

cut有一個着名和短的perl workalike,這是一個更有特色的這個主題variaton,並有this Perl Monks thread

+0

'perl -anE'說$ F [1]如果/ \ S /''會跳過空行。 –

0

perl -a -F' ' -ne 'print "$F[0]\n";' data.txt

在這裏你$ F [0]字段,你可以改變它相應的你會得到預期的輸出