2013-04-04 52 views
0

我試圖以可以訪問行中每列的方式將CSV讀取到數組中。但是,當我運行以下代碼以打印每行的特定列時,它只輸出空行。將選項卡分隔文件解析爲數組

#set command line arguments 
my ($infi, $outdir, $idcol) = @ARGV; 

#lead file of data to get annotations for 
open FILE, "<", $infi or die "Can't read file '$infi' [$!]\n"; 
my @data; 
foreach my $row (<FILE>){ 
    chomp $row; 
    my @cells = split /\t/, $row; 
    push @data, @cells; 
} 


#fetch genes 
foreach (@data){ 
    print "@_[$idcol]\n"; 
# print $geneadaptor->fetch_by_dbID($_[$idcol]); 
} 

隨着

a  b  c 
1  2  3 
d  e  f 
4  5  6 

測試輸入我覺得這裏的問題與其說加載該文件,但在處理所得到的陣列。我應該如何解決這個問題?

+0

你確定不應該使用散列而不是數組嗎? – 2013-04-04 16:48:30

+0

散列是否相當於一個python字典?如果是這樣,那麼使用它會更有意義。 – Joe 2013-04-05 12:53:51

回答

1

我建議避免直接解析CSV文件並使用Text::CSV模塊。

use Text::CSV; 
use Carp; 

#set command line arguments 
my ($infi, $outdir, $idcol) = @ARGV; 

my $csv = Text::CSV->new({ 
    sep_char => "\t" 
}); 

open(my $fh, "<:encoding(UTF-8)", $infi) || croak "can't open $infi: $!"; 

# Uncomment if you need to skip header line 
# <$fh>; 

while (<$fh>) { 
    if ($csv->parse($_)) { 
     my @columns = $csv->fields(); 
     print "$columns[0]\t$columns[1]\t$columns[2]\n"; 
    } else { 
     my $err = $csv->error_input; 
     print "Failed to parse line: $err"; 
    } 
} 
close $fh; 
+0

[文本/製表符分隔值MIME類型](http://www.iana.org/assignments/media-types/text/tab-separated-values)的定義非常簡單,因此數據不能包含製表符。沒有引號或轉義字符,因此解析製表符分隔數據的正確方法是使用簡單的'split/\ t /'。要正確設置'Text :: CSV',你還必須禁止'quote_char'和'escape_char',它最終應該只是在選項卡上進行分割,並且模塊將失去其全部的值。 – Borodin 2013-04-04 17:22:24

+0

感謝您的提示,但提問者說「我正在嘗試閱讀CSV」,所以我不能假設該文件不包含引號或轉義字符... – 2013-04-04 18:00:50

+0

這顯然是一個誤解,因爲CSV是,根據定義,用逗號分隔。 – Borodin 2013-04-04 19:42:21

4

首先你需要push @data, \@cells,否則你會把所有的字段連成一個列表。

然後,您需要在第二個for循環中使用循環值。

foreach (@data){ 
    print $_->[$idcol], "\n"; 
} 

@_是從$_一個完全不同的可變的,並且未填充這裏。

你也應該考慮使用

while (my $row = <FILE>) { ... } 

閱讀您的文件。它一次只讀取一行,而for將在遍歷它之前將整個文件讀入行列表。