使用Text :: CSV解析Perl中的制表符分隔文件

时间:2013-10-12 18:23:01

标签: regex perl parsing tab-delimited tab-delimited-text

我正在尝试使用Text::CSV Perl模块来解析制表符分隔文件。

我要解析的文件是:

#IGNORE COLUMN1 COLUMN2 COLUMN3 COLUMN4
ROW1    x   y   z   a
ROW2    b   c   d   
ROW3    w

请注意,该文件是制表符分隔的。此文件可能包含N列和N行。此外,在ROW2的情况下,它有第四个选项卡但没有值。在ROW3的{​​{1}}值之后,w没有标签。即某些列可能包含未定义的值或空值。

到目前为止,我已经开始编写Perl脚本了,但是在尝试弄清楚如何编写代码来回答以下问题时,我们很早就磕磕绊绊了:

找出有多少COLUMN1。然后对每个ROWn检查一下,看看我是否有COLUMNn个值。因此,在这种情况下,ROWnCOLUMN2COLUMN3会丢失值。

任何提示和指导都会有所帮助(我是Perl的新手)。我查看了CPAN Text :: CSV页面,但我无法解决这个问题。

COLUMN4

1 个答案:

答案 0 :(得分:0)

一种方法,每行处理每个字段,并在不是false时递增计数器:

#!/usr/bin/env perl

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

my (@col_counter); 
my ($line_counter, $r, $num_cols) = (0, 0, 0); 

open my $fh, '<', shift or die;

my $csv = Text::CSV_XS->new({
    sep_char => qq|\t|
});

while ( my $row = $csv->getline( $fh ) ) { 
    ## First row (header), get the number of columns.
    if ( $line_counter == 0 ) { 
        $num_cols = $#$row;
        next;
    }
    ## For each data row, traverse every column and increment a 
    ## counter if it has any value.
    for ( 1 .. $#$row ) { 
        ++$col_counter[ $_ ] if $row->[ $_ ];
    }   
}
continue {
    $line_counter++;
}

printf qq|Lines of file: %d\n|, $line_counter - 1;
## Check if any column has missing values. For each column compare the 
## number of lines read (substract 1 of header) with its counter. If they
## are different it means that the column had any row without value.
for my $i ( 1 .. $num_cols ) { 
    $r = $line_counter - 1 - (defined $col_counter[ $i ] ? $col_counter[ $i ] : 0); 
    if ( $r > 0 ) { 
        printf qq|Column %d has %d missing values\n|, $i, $r;  
    }   
}

使用您的示例数据,运行它:

perl script.pl infile

产量:

Lines of file: 3
Column 2 has 1 missing values
Column 3 has 1 missing values
Column 4 has 2 missing values

更新:查看评论。我反过来查找不包含任何值的列,并将当前行号附加到数组,并使用join提取所有行。

我改变了哪些部分?这里是为了保存行号。

for ( 1 .. $num_cols ) { 
    push @{ $col_counter[ $_ ] }, $line_counter unless $row->[ $_ ];
}

在这里打印它们。您需要评论旧行为。

if ( defined $col_counter[ $i ] ) { 
    printf qq|Column %d has no value in lines %s\n|, $i, join q|,|, @{ $col_counter[ $i ] };
}

它产生:

Lines of file: 3
Column 2 has no value in lines 3
Column 3 has no value in lines 3
Column 4 has no value in lines 2,3