Извлечение уникальных значений из нескольких файлов в Perl - PullRequest
1 голос
/ 02 февраля 2011

У меня есть несколько файлов данных с разделителями табуляции. Мне нужно извлечь все уникальные значения в определенном столбце этих файлов данных (скажем, столбец 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);
}

Вопрос в том, как эффективно создать хэш / массив уникальных значений, когда я читаю каждую строку каждого файла. Или это быстрее, если я заполню весь массив, а затем удалю дубликаты?

Ответы [ 3 ]

3 голосов
/ 02 февраля 2011

Несколько советов о том, как решить проблему:

  • Поиск файлов
    • Для поиска файлов в каталоге используйте glob: glob '.* *'
    • Для поиска файлов в дереве каталогов используйте File::Find find function
  • Откройте каждый файл, используйте Text::CSV с символом \t в качестве разделителя, извлеките нужные значения и запишите в файл
3 голосов
/ 02 февраля 2011

Для решения Perl, пожалуйста, используйте модуль Text::CSV для анализа плоских (X-разделенных) файлов - конструктор принимает параметр, указывающий символ разделителя.Сделайте это для каждого файла в цикле со списком файлов, сгенерированным либо glob() для файлов в данном каталоге, либо File::Find для подкаталогов

Затем, чтобы получить уникальные значения для каждой строки,сохранить столбец № 25 в хэше.

Например, после получения значений:

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

Затем выполнить итерацию по ключам хеш-функции и распечатать в файл.* Для решения без оболочки Perl вы можете просто сделать:

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

Вы можете заменить awk на cut

Обратите внимание, что решение не на Perl работает, только если файлыне содержат табуляции в самих полях, а столбцы не заключаются в кавычки.

2 голосов
/ 02 февраля 2011
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 ...
...