如何使用Perl从制表符分隔文件中提取特定列?

时间:2011-08-17 13:22:05

标签: perl

我是Perl的新手,并且一直试图为此解决问题。当我运行这个程序时,我没有收到任何错误,也没有显示任何内容。

代码如下:

#!/usr/bin/perl
open (DATA, "<test1.txt") or die ("Unable to open file");
use strict; use warnings;
my $search_string = "Ball";
while ( my $row = <DATA> ) {

    last unless $row =~ /\S/;
    chomp $row;
    my @cells = split /\t/, $row;

    if ($cells[0] =~/$search_string/){
        print $cells[0];
    }
}

我的测试数据文件如下所示

Camera Make     Camera Model    Text    Ball    Swing
a       b       c       d       e
f       g       h       i       j
k       l       m       n       o

我试图在使用实际的测试数据文件之前看看它是如何工作的。

那么如何搜索说“Ball”并让它返回“d i n”

4 个答案:

答案 0 :(得分:2)

您没有收到任何错误的原因是因为您的程序完全按照您的说法执行(打印包含字符串“Ball”的所有第一列值)。由于第一列中没有任何单元格包含该字符串,因此您的程序不会打印任何内容。

你的问题不在你的Perl上(它可能会使用一些较小的风格改进 - 特别是你使用过时的open()形式 - 但大多数情况下都很好),你的算法是

提示:算法中的第一个任务应该是找到WHICH列(按编号)是“Ball”列。

答案 1 :(得分:2)

试试这个:

use strict;
use warnings;
use Data::Dumper;
use List::MoreUtils qw<first_index>;

my $column = first_index { $_ eq 'Ball' } split /\t/, <DATA>;
say Data::Dumper->Dump( [ $column ], [ '*column' ] );
my @balls  = map { [split /\t/]->[$column] } <DATA>;
say Data::Dumper->Dump( [ \@balls ], [ '*balls' ] );
__DATA__
Camera Make Camera Model    Text    Ball    Swing
a   b   c   d   e
f   g   h   i   j
k   l   m   n   o

您几乎必须将句柄从DATA更改为某个文件open - 编辑。

open( my $in, '<', '/path/to/data.file' ) 
    or die "Could not open file: $!"
    ;

然后将<DATA>替换为<$in>

答案 2 :(得分:0)

请改为尝试:

#!/usr/bin/perl
use strict;
use warnings;

open (DATA, "<test1.txt") or die ("Unable to open file");
my $search_string = "Ball";

my $header = <DATA>;
my @header_titles = split /\t/, $header;
my $extract_col = 0;

for my $header_line (@header_titles) {
  last if $header_line =~ m/$search_string/;
  $extract_col++;
}

print "Extracting column $extract_col\n";

while ( my $row = <DATA> ) {
  last unless $row =~ /\S/;
  chomp $row;
  my @cells = split /\t/, $row;
  print "$cells[$extract_col] ";
}

答案 3 :(得分:0)

您可以使用Text::CSV_XS非常方便地为您提取数据。对于您的有限数据可能有点过分,但这是一个非常可靠的解决方案。

此处我只使用 DATA 标记来包含数据,但如果您愿意,可以将其替换为文件句柄,例如open my $fh, '<', 'text1.txt';并将*DATA更改为$fh

<强>输出:

d i n

<强>代码:

use warnings;
use strict;
use Text::CSV_XS;
use autodie;

my $csv = Text::CSV_XS->new( { sep_char => "\t" } );
my @list;
$csv->column_names ($csv->getline (*DATA));
while ( my $hr = $csv->getline_hr(*DATA) ) {
    push @list, $hr->{'Ball'};
}

print "@list\n";
__DATA__
Camera Make Camera Model    Text    Ball    Swing
a   b   c   d   e
f   g   h   i   j
k   l   m   n   o

ETA:如果你要削减&amp;粘贴以试用它,确保选项卡在数据中被转移。