当尝试从sub打印数组时,只打印第一个元素

时间:2014-03-14 20:18:35

标签: perl subroutine

我正在编写一个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)。

4 个答案:

答案 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所需的列数。这可以显着加快这一过程。
  • (可选)使用文件名初始化Perl 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;
}

希望这有帮助!