2016-07-19 5 views
2

Ich habe zwei Arten von durch Tabulatoren getrennten Eingabedateien, die erste ist eine Matrix, deren Namen in der ersten Spalte vertikal aufgelistet sind, und numerische Werte in nachfolgenden Spalten. Der zweite Eingabetyp enthält eine einzelne Spalte mit einer Untergruppe derselben Namen, die in der ersten Spalte des ersten Dateityps aufgeführt sind.Codierung eines awk-Befehls in einem Perl-Skript

EX: input1

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

EX: input2

Gary 
Biff 

Zwar gibt es verschiedene Variationen input2, gibt es nur eine einzige input1. Ich habe ein Perl-Skript mit einem eingebetteten awk-Befehl, der Namen von Eingabe2 bis Eingabe1 abgleichen soll und eine Ausgabedatei ausgeben soll, die die Namen von Eingabe2 und die entsprechenden Werte von Eingabe1 enthält.

EX: output

Gary 1 2 3 
Biff 5 6 7 

Hier ist mein Code:

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

Das ist die Linie auf der Kommandozeile funktioniert, aber es weigert sich, in meinem Perl-Skript zu arbeiten.

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 

By the way, die schiere Anzahl der input2 Dateien macht hart, um die oben awk Leitungscodierung auf dem Befehl einen echten Schmerzen in dem Hintern propt, weshalb ich einen Perl-Skript verwendet habe, die meine gewünschte Funktion ausführen können, auf jede Input2-Datei im Verzeichnis UND die Namenskonvention für die Ausgabedateien beibehalten. Ich habe ähnliche Programme geschrieben, so dass ich die Syntax von

kann und richtig funktioniert.

Ich bin seit Tagen auf dieses Problem fest, so würde jede Hilfe am meisten geschätzt werden!

+1

ich Sie Hash verwenden, um würde vorschlagen, passen diese Art von Problem zu lösen. Das wird schneller sein. – Arijit

+0

Was meinst du mit Hash? –

+1

Ein gutes Dokument von Hash finden Sie in diesem Link. http://www.tutorialspoint.com/perl/perl_hashes.htm – Arijit

Antwort

0

Während es bei Input2 verschiedene Variationen gibt, gibt es nur einen einzigen Eingang1. Ich habe ein Perl-Skript mit einem eingebetteten awk Befehl , der Namen von Eingang2 zu Eingang1 übereinstimmen und eine Ausgabedatei drucken soll, die die Namen von Eingang2 und die entsprechenden Werte von Eingang1 enthält.

würde ich find vorschlagen + a comparison function Ihr Ziel

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]"' _ {} + 

Referenzen

  1. Die {} + mit Fund zu erreichen baut die Befehlszeile und führen Sie den Sub-Shell-Befehl, unsere Funktion in dieser Fall, einmal für alle. Siehe [ find ] Hilfeseite.

  2. Beachten Sie, dass ich >> verwendet habe, um die Ausgabe nachfolgender Läufe an die Ausgabedatei anzuhängen. Wenn dies nicht gewünscht ist, verwenden Sie >.

  3. Das Muster mit -name sollten alle input2 Dateinamen angepasst werden

+1

Dieser kurze Ansatz wird in puncto Geschwindigkeit nicht annähernd "perl" sein. –