我有几个以制表符分隔的数据文件。我需要提取这些数据文件的某一列中的所有唯一值(比如第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);
}
问题是当我读取每个文件的每一行时,如何有效地创建唯一值的散列/数组。或者,如果我填充整个数组然后删除重复项,它会更快吗?
答案 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)
有关如何处理问题的一些提示:
glob
:glob '.* *'
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 ...