2013-04-04 54 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将在遍历它之前将整个文件读入行列表。