簡體   English   中英

從Perl中的多個文件中提取唯一值

[英]Extracting unique values from multiple files in Perl

我有幾個制表符分隔的數據文件。 我需要提取這些數據文件的某一列(例如第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);
}

問題是當我讀取每個文件的每一行時,如何有效地創建唯一值的哈希/數組。 或者,如果我填充整個數組然后刪除重復項,它會更快嗎?

對於Perl解決方案,請使用Text::CSV模塊來解析平面(X分隔)文件-構造函數接受指定分隔符的參數。 對循環中的每個文件執行此操作,並使用glob()生成給定目錄中的File::FindFile::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

您可以用cut替換awk

請注意,非Perl解決方案僅在文件本身中的字段中不包含TAB且未引用各列​​的情況下才有效。

有關如何處理該問題的一些技巧:

  • 查找文件
    • 要在目錄中查找文件,請使用globglob '.* *'
    • 要在目錄樹中查找文件,請使用File::Findfind函數
  • 打開每個文件,使用\\t字符的Text::CSV作為分隔符,提取所需的值並寫入文件
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 ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM