2011-08-17 90 views
0

我在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 

我想看看它是如何工作之前,我使用的实际测试数据文件..

那么我该如何搜索说“球”并让它返回“din”

+1

你不是要求帮助Perl。你要为你写一份作业,因为你上面的代码与你最后一行所要求的无关。请写一个你正在试图用Perl实现的算法,然后问你为什么Perl的实现不起作用 - 目前,你的问题的答案是“你的代码与你的任务是无关的” – DVK

+0

我保证这个是不是任务...但无论如何...这怎么不适用..我正在定义我正在寻找的东西,并通过/ \ t /分裂文本,这是我相信的标签,并将其存储在一个数组中..我在问什么是“我如何搜索该数组并获取相关列? –

+1

请参阅我的答案中的提示。您正在解析文件;您只是没有使用解决问题的逻辑/算法。暗示应该足以让你的球滚动(没有双关语意思) – DVK

回答

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] "; 
} 
+0

这个作品......但我不明白你是如何做它做的...当你说'我的$ header = '将文件放入$ header,然后放入@header标题通过选项卡点亮头文件,但不会将列名放在行而不是列中? –

+0

@David:这不是<>的工作原理。在标量上下文中,它从文件中读取一行。 [请阅读perlop手册的I/O操作员部分](http://perldoc.perl.org/perlop.html)。 –

+1

如果你使用**三个参数[open](http://perldoc.perl.org/functions/open.html) –

2

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

你的问题不在于你的Perl(它可以使用一些小的改进风格 - 特别是你使用的open()过时的形式 - 但大多是罚款),它是有你的算法

提示:在算法中你的首要任务应该是寻找哪一列(按编号)是“球”专栏。

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 

埃塔:如果你打算削减&粘贴尝试一下,确保标签结转在数据中。

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 -ed。

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

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

+0

+1很酷的解决方案;) – TLP

相关问题