我正在编写一个Perl脚本,要求我从文件中提取整个列并对其进行操作。例如,取出A列并将其与另一个文件中的另一列进行比较
A B C
A B C
A B C
到目前为止,我有:
sub routine1
{
( $_ = <FILE> )
{
next if $. < 2; # to skip header of file
my @array1 = split(/\t/, $_);
my $file1 = $array1[@_];
return $file1;
}
}
我完成了大部分工作。唯一的问题是,当我调用打印子程序时,它只打印数组中的第一个元素(即它只打印一个A)。
答案 0 :(得分:1)
我确信你实际拥有的是这个
sub routine1
{
while ( $_ = <FILE> )
{
next if $. < 2; # to skip header of file
my @array1 = split(/\t/, $_);
my $file1 = $array1[@_];
return $file1;
}
}
进行编译,并在循环中一次读取一行文件。
这里有两个问题。首先,只要您的循环读取了文件的第一行(在标题之后),return
语句就会退出子例程,返回它已读取的唯一字段。这就是为什么你只得到一个值。
其次,您已使用@array1
将@_
编入索引。这样做的是@_
中的元素数量(通常是一个)并使用它来索引@array1
。因此,您将始终获得数组的第二个元素。
我不清楚你期望的结果,但你应该写这样的东西。它将指定列中的所有值累加到数组@retval
中,并将文件句柄传递给子例程,而不是仅仅使用全局,这是一种糟糕的编程习惯。
use strict;
use warnings;
open my $fh, '<', 'myfile.txt' or die $!;
my @column2 = routine1($fh, 1);
print "@column2\n";
sub routine1 {
my ($fh, $index) = @_;
my @retval;
while ($_ = <$fh>) {
next if $. < 2; # to skip header of file
my @fields = split /\t/;
my $field = $fields[$index];
push @retval, $field;
}
return @retval;
}
<强>输出强>
B B
答案 1 :(得分:0)
尝试使用以下内容替换大部分潜艇:
my @aColumn = ();
while (<FILE>)
{
chomp;
($Acol, $Bcol, $Ccol) = split("\t");
push(@aColumn, $Acol);
}
return @aColumn
答案 2 :(得分:0)
跳到最后,以下内容将拉出文件blah.txt
中的第一列并将其放入数组中供您稍后操作:
use strict;
use warnings;
use autodie;
my $file = 'blah.txt';
open my $fh, '<', $file;
my @firstcol;
while (<$fh>) {
chomp;
my @cols = split;
push @firstcol, $cols[0];
}
use Data::Dump;
dd \@firstcol;
你现在所拥有的并不是实际循环文件的内容,所以你不会构建一个数组。
答案 3 :(得分:0)
在制作用于从文件中获取列值数组的子例程解决方案时,您可以考虑以下几个项目:
while
循环之前跳过文件标题,以避免每个文件行的行号比较。split
仅使用split
的LIMIT所需的列数。这可以显着加快这一过程。local
的{{1}}副本,并让Perl处理文件i / o。Borodin创建一个同时包含文件名列号的子程序的解决方案非常好,所以它也在下面实现:
@ARGV
数据集输出:
use strict;
use warnings;
my @colVals = getFileCol( 'File.txt', 0 );
print "@colVals\n";
sub getFileCol {
local @ARGV = (shift);
my ( $col, @arr ) = shift;
<>; # skip file header
while (<>) {
my $val = ( split ' ', $_, $col + 2 )[$col] or next;
push @arr, $val;
}
return @arr;
}
希望这有帮助!