使用Perl正则表达式解析制表符分隔文件

时间:2013-10-09 21:33:07

标签: regex perl

我试图弄清楚如何使用正则表达式能够从制表符分隔的文本文件中“提取”特定文本,并对下面的文件执行操作。

我有一个文件格式如下:

#HEADER_IGNORE        HEADING1     HEADING2      HEADINGN
Some Text Here        value        value2        value3
SOME_TEXTHERE         x                          z
Some More Text Here   A            B             

我希望能够提取第一个“专栏”。基本上,我想在第一个选项卡之前获取所有文本,以便我的正则表达式能够提取:

Some Text Here
SOME_TEXTHERE
Some More Text Here

我试图使用以下正则表达式而没有任何运气。

/(\W\s)*\t$/

现在我希望能够做的第二件事就是告诉任何行x列引用是否缺少值。即在上面的示例文件中,行标识SOME_TEXTHERE缺少HEADING2的值。可能有任意数量的行ID和列。

提前致谢!

2 个答案:

答案 0 :(得分:1)

经典的方法是chomp每一行删除行终止符,然后split /\t/提取所有字段值的列表。

chomp;
my @fields = split /\t/;
my $field1 = $fields[0];

但是,如果您确定只有想要第一列,最简单的方法是找到不是的行开头的所有字符标签。

my ($field1) = /\A([^\t]+)/;

鉴于您的第二个要求,其中第一个是最好的。这取决于“缺失值”的含义,但只要所有制表符分隔符在那里,您就可以通过编写来检查以确保一行具有给定数量的字段

my $n = grep /\S/, @fields;
warn "Missing field" unless $n == 4;

或者,如果您想要发现哪个字段缺失,那么

my @missing = map { $fields[$_-1] !~ /\S/ } 1 .. 4;
warn "Missing field $missing[0]" if @missing;

答案 1 :(得分:-1)

我是哈希的忠实粉丝,所以我会使用哈希 因为如果缺少数组中的最后一个元素,split不起作用,如果最后一个元素是\t,我们必须手动添加一个空字符串(这样缺少的列将变为空字符串)。

例如,如果$rows{SOME_TEXTHERE}[1] eq ""

,您将知道缺少哪一列
#!/usr/bin/perl

use strict;
use warnings;

chomp(my $first_line = <STDIN>);
my $length = scalar(split /\t/, $first_line);

my %rows;
while (<STDIN>) {
    chomp;
    my @row = split /\t/;
    push @row, "" for 1..$length - scalar @row;
    # Assuming there's ALWAYS a row ID
    my $id = shift @row;
    $rows{$id} = [@row];
}

foreach my $rowID (keys %rows) {
    for (my $i = 0; $i < @{$rows{$rowID}}; $i++) {
        # Column 1 being the id
        printf "missing column #%d in %s\n", $i + 1, $rowID
            if $rows{$rowID}[$i] eq "";
    }
}