【问题标题】:Extracting unique values from multiple files in Perl从 Perl 中的多个文件中提取唯一值
【发布时间】:2011-06-19 22:16:17
【问题描述】:

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

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

#!/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);
}

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

【问题讨论】:

  • @davorg 好吧,我被基本问题本身所困扰。首先,我如何一次读取多个文件。下一个是在我读取每个文件时只考虑唯一值。我猜可以使用 Find::File 包。
  • @DVK yes 是已经在 Perl 中的更大代码的一部分。
  • 您通常不应该使用 split 来解析 X 分隔的文件。除了最微不足道的情况外,这还不够——例如不处理字段内的 X(分隔符)或被引用的字段。不过,在微不足道的情况下它可以工作

标签: perl parsing file


【解决方案1】:

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

  • 查找文件
    • 要在目录中查找文件,请使用glob:glob '.* *'
    • 要在目录树中查找文件,请使用File::Find 的find 函数
  • 打开每个文件,使用Text::CSV和\t字符作为分隔符,提取想要的值并写入文件

【讨论】:

  • 都是正确的,但是 OP 可能需要一个具体的例子来说明另一个
【解决方案2】:

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

然后,为了获得唯一值,对于每一行,将第 25 列存储在哈希中。

例如检索值后:

 $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 且列未引用的情况。

【讨论】:

  • 我已经成功使用了 glob() 函数。但是我是 perl 的新手,所以对于您所说的将值存储在哈希中并对其进行迭代的部分有点困惑?你能告诉我怎么做吗?
【解决方案3】:
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 ...

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多