2016-07-19 2 views
2

У меня есть два типа входных файлов с разделителями вкладок, первая - это матрица, которая имеет имена, перечисленные вертикально в первом столбце, и числовые значения в последующих столбцах. Второй тип ввода содержит один столбец с подмножеством тех же имен, который указан в первом столбце первого типа файла.Кодирование команды awk внутри скрипта perl

EX: вход1

Gary 1 2 3 
Yolanda 3 4 5 
Biff 5 6 7 
Hubert 8 9 10 

EX: вход2

Gary 
Biff 

В то время как существует несколько различных вариаций на input2, есть только один вход1. У меня есть скрипт perl со встроенной командой awk, которая должна соответствовать именам от input2 до input1 и печатать выходной файл, который содержит имена из input2 и соответствующие значения из input1.

EX: выходной_файл

Gary 1 2 3 
Biff 5 6 7 

Вот мой код:

#!/usr/bin/perl 

use strict; 
use warnings; 

my $dir1 = '../FeatureSelection/Chunks/ArffPreprocessing'; 
my $dir2 = '../DataFiles'; 

opendir(DIR, $dir1) or die $!; 
while (my $file = readdir(DIR)) { 

    # We only want files 
    next unless (-f "$dir1/$file"); 

    # Use a regular expression to find files with .txt 
    next unless ($file =~ m/\.txt/); 

    my @partialName = (split /\./, $file); 

    #The $matchingFile is the file which contains attributes listed vertically, along side their respective data 

    my $matchingFile = "$dir2/input1\.txt "; 

    system("awk -F\"\t\" 'FILENAME==\"$dir1/$file\"{a[\$1]=\$1} FILENAME==\"$matchingFile\"{if(a[\$1]){print \$0}}' $dir1/$file $matchingFile > $dir1/$partialName[0]'\_matched.out' "); 

} 

closedir(DIR); 
exit 0; 

Это линия работает в командной строке, но он отказывается работать в моем PERL скрипт.

awk -F"\t" 'FILENAME=="input2.txt"{a[$1]=$1} FILENAME=="../../../DataFiles/input1.txt"{if(a[$1]){print $0}}' input2.txt ../../../DataFiles/input1.txt > input2_matched.out 

Кстати, огромное количество Input2 файлов делает жестким кодирование выше AWK линии на команду propt реальной боли в заднице, поэтому я использовал PERL скрипт, который может выполнять свою требуемую функцию на каждый файл input2 в каталоге, И сохраняйте соглашение об именах для выходных файлов. Я написал аналогичные программы, поэтому я знаю синтаксис

system("awk ...blah blah... "); 

может и правильно работать.

Я застрял в этой проблеме в течение нескольких дней, поэтому любая помощь была бы очень признательна!

+1

Я хотел бы предложить вам использовать хэш для решения такого рода проблем. это будет быстрее. – Arijit

+0

Что вы понимаете под хэш? –

+1

Хороший документ хэша вы найдете в этой ссылке. http://www.tutorialspoint.com/perl/perl_hashes.htm – Arijit

ответ

0

Несмотря на то, что на входе 2 имеется несколько различных вариаций, имеется только один вход1. У меня есть скрипт perl со встроенной командой awk , которая должна соответствовать именам от input2 к input1 и печатать выходной файл , который содержит имена от input2 и соответствующие значения от input1.

Я хотел бы предложить find + a comparison function для достижения вашей цели

matcher(){ 
awk 'NR==FNR{input1record[$1]=$0;next} 
    $1 in input1record{print input1record[$1]}' /path/to/input1 "[email protected]" >> /path/to/result 
} 
export -f matcher 
find /path/to/input2_files -type f -name "input2" \ 
    -exec bash -c 'matcher "[email protected]"' _ {} + 

Ссылки

  1. {} + с находкой строит командную строку и выполнить команду подоболочку, нашу функцию в этот случай, раз для всех. См. [ find ] manpage.

  2. Примечание. Я использовал >>, чтобы добавить выходные данные последующих прогонов к выходному файлу. Если это нежелательно, используйте >.

  3. Узор с -name должен быть отрегулирован, чтобы соответствовать всем input2 имен файлов

+1

Этот подход, хотя и короткий, не будет находиться рядом с 'perl', когда дело доходит до скорости. –

Смежные вопросы