从Perl中的多个文件中提取唯一值

时间:2011-02-02 11:37:42

标签: perl parsing file

我有几个以制表符分隔的数据文件。我需要提取这些数据文件的某一列中的所有唯一值(比如第25列),并将这些值写入输出文件以供进一步处理。我怎么能在Perl中这样做?请记住,我需要考虑同一文件夹中的多个文件。

编辑:到目前为止,我所做的代码是这样的。

#!/usr/bin/perl                   

use warnings;
use strict;

my @hhfilelist  = glob "*.hh3";

for my $f (@hhfilelist) {
  open F, $f || die "Cannot open $f: $!";
  while (<F>) {
    chomp;
    my @line = split /\t/;   

    print "field is $line[24]\n";
  }
  close (F);
}

问题是当我读取每个文件的每一行时,如何有效地创建唯一值的散列/数组。或者,如果我填充整个数组然后删除重复项,它会更快吗?

3 个答案:

答案 0 :(得分:3)

对于Perl解决方案,请使用Text::CSV模块解析平面(X分隔)文件 - 构造函数接受指定分隔符的参数。对循环中的每个文件执行此操作,文件列表由glob()为给定目录中的文件生成,或File::Find为子目录生成

然后,为获取每行的唯一值,将列#25存储在散列中。

E.g。检索值后:

 $colref = $csv->getline($io);
 $unique_values_hash{ $colref->[24] } = 1;

然后,迭代哈希键并打印到文件。


对于非Perl shell解决方案,您只需执行以下操作:

cat MyFile_pattern | awk -F'\t' 'print $25' |sort -u > MyUniqueValuesFile

您可以将awk替换为cut

请注意,非Perl解决方案仅在文件本身不包含TAB且未引用列时才有效。

答案 1 :(得分:3)

有关如何处理问题的一些提示:

  • 查找文件
    • 要查找目录中的文件,请使用globglob '.* *'
    • 要查找目录树中的文件,请使用File::Find&#39; find功能
  • 打开每个文件,使用带有\t字符的Text::CSV作为分隔符,提取所需值并写入文件

答案 2 :(得分:2)

perl -F/\\t/ -ane 'print"$F[24]\n" unless $seen{$F[24]}++' inputs > output

perl -F/\\t/ -ane 'print"$F[24]\n" unless $seen{$F[24]}++' *.hh3 > output

命令行开关-F/\\t/ -an表示遍历每个输入文件中的每一行,并将制表符上的行拆分为数组@F

$F[24]指的是每行第25个字段中的值(第24个和第25个制表符之间)

$seen{...}是一个哈希表,用于跟踪已经观察到的值。 第一次观察到值时,$seen{VALUE}为0,因此Perl将执行语句print"$F[24]\n"。每隔一段时间观察一次值,$seen{VALUE}将为非零,并且不会执行该语句。这样,每个唯一值只打印一次。


在与较大脚本类似的上下文中:

my @hhfilelist  = glob "*.hh3";
my %values_in_field_25 = ();
for my $f (@hhfilelist) {
  open F, $f || die "Cannot open $f: $!";
  while (<F>) {
    my @F = split /\t/;
    $values_in_field_25{$F[24]} = 1;
  }
  close (F);
}

my @unique_values_in_field_25 = keys %values_in_field_25; # or sort keys ...