2009-04-21 3 views
2

Nehmen wir an, ich habe eine tabulatorgetrennte Textdatei, die Daten enthält, die in Spalten angeordnet sind (mit Kopfzeilen).Gibt es ein Perl-Modul zum Analysieren von Säulenschrift?

Es ist möglich, dass verschiedene Spalten zu einer "Arbeitsblatt" -artigen Anordnung "gestapelt" werden können, d. H. Es gibt einen Teiler (der vorher bekannt sein kann oder nicht), der es ermöglicht, verschiedene Spalten vertikal anzuordnen.

Gibt es ein Perl-Modul, das das Analysieren von Spaltendaten in dieser Textdatei in eine Datenstruktur erleichtert (z. B. eine Hash-Tabelle mit dem Schlüssel als Spaltenüberschrift und dem Wert als Array mit Spaltendatenskalaren)?

EDIT Mit "stacked", ich meine, dass eine Spalte Text mehrere, einzelne "Vektoren" von Daten enthalten kann, jeder mit unterschiedlichen Überschriften und verschiedenen Längen. Zugegebenermaßen kompliziert dies das Parsen.

EDIT Ich bin ehrlich gesagt nicht sicher, wo die Verwirrung ist. Dennoch hier ein Beispiel: header_one, header_two, header_three und header_four, jede Taste Referenzierung einen Array Referenz Unter Hinweis auf die data_n Elemente unterhalb der Kopfzeile:

header_one\theader_three 
data_1\tdata_7 
data_2\tdata_8 
data_3\tdata_9 
\tdata_10 
header_two\tdata_11 
data_4\theader_four 
data_5\tdata_12 
data_6\tdata_13 
\tdata_14 

Das Skript diese in eine Hash-Tabelle mit vier Tasten drehen würde.

+0

Sie müssten wahrscheinlich ein Beispiel zeigen ... Ich habe eine schwere Zeit zu visualisieren. – Tanktalus

+0

Ich glaube nicht, dass ich ein Beispiel habe, das ich leicht auf dieser Seite einfügen und formatieren kann. Stellen Sie sich nur eine Spalte mit Daten (mit einem eindeutigen Header) und eine andere direkt darunter (mit einem anderen, eindeutigen Header) vor. –

+0

EIN BEISPIEL ZEIGEN! Wenn du willst, dass irgendjemand etwas erfindet, das funktionieren wird. –

Antwort

2

Ich denke, das ist in der Nähe, was Sie reden. Wenn sich die Anzahl der Spalten ändert, wird die Eingabe wie eine andere Tabelle behandelt. Dieser Code könnte leicht modifiziert werden, um einen anderen Marker (z. B. eine Zeile mit gleichen Vorzeichen) zu erkennen, anstatt die Spaltenanzahl zu verwenden.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Text::CSV_XS; 

#setup the parser, here we want tab separated and we allow 
#loose quoting, so qq/foo\t"bar\tbaz"\tquux/ is 
#("foo", "bar\tbaz", "quux") 
my $p = Text::CSV_XS->new(
    { 
     sep_char   => "\t", 
     allow_loose_quotes => 1, 
    } 
); 

my @stacked; 
my $cur = 0; 
while (<>) { 
    $p->parse($_) or die $p->error_input; 
    my @rec = $p->fields; 
    #normal case, just add the record to the last 
    #section in @stacked 
    if (@rec == $cur) { 
     push @{$stacked[-1]}, \@rec; 
     next; 
    } 
    #if the number of columns don't match then 
    #we have a new section 
    push @stacked, [\@rec]; 
    $cur = @rec; #set the new number of columns 
} 

for my $table (@stacked) { 
    print "header: ", join("::", @{$table->[0]}), "\n"; 
    for my $i (1 .. $#$table) { 
     print "data: ", join("::", @{$table->[$i]}), "\n"; 
    } 
    print "\n"; 
} 
2

Ich würde mit DBD::CSV starten, wenn möglich, obwohl Ihre "gestapelte" Anforderung (die ich nicht vollständig verstehe) würde wahrscheinlich einige manuelle Analyse benötigen, mit Text::CSV_XS.

Lassen Sie sich nicht von ihren Namen täuschen - sie können mit jedem Trennzeichen, nicht nur mit Kommas, arbeiten.

-1

nicht sehr glatt, aber ich habe es wie folgt tun:

 my $recordType = unpack("A3", $_); 

     if ($recordType eq "APT") 
     { 
      $currentKey = parseFAAAirportAirportRecord($_); 
     } 
     elsif ($recordType eq "ATT") 
     { 
      parseFAAAirportAttendenceRecord($currentKey, $_); 
     } 
     elsif ($recordType eq "RWY") 
     { 
      parseFAAAirportRunwayRecord($currentKey, $_); 
     } 
     elsif ($recordType eq "RMK") 
     { 
      parseFAAAirportRemarkRecord($currentKey, $_); 
     } 
... 
sub parseFAAAirportAirportRecord($) 
{ 
    my ($line) = @_; 

    my ($recordType, $datasource_key, $type, $id, $effDate, $faaRegion, 
     $faaFieldOffice, $state, $stateName, $county, $countyState, 
     $city, $name, $ownershipType, $facilityUse, $ownersName, 
     $ownersAddress, $ownersCityStateZip, $ownersPhone, $facilitiesManager, 
     $managersAddress, $managersCityStateZip, $managersPhone, 
     $formattedLat, $secondsLat, $formattedLong, $secondsLong, 
     $refDetermined, $elev, $elevDetermined, $magVar, $magVarEpoch, $tph, 
     $sectional, $distFromTown, $dirFromTown, $acres, 
     $bndryARTCC, $bndryARTCCid, 
     $bndryARTCCname, $respARTCC, $respARTCCid, $respARTCCname, 
     $fssOnAirport, $fssId, $fssName, $fssPhone, $fssTollFreePhone, 
     $altFss, $altFssName, 
     $altFssPhone, $notamFacility, $notamD, $arptActDate, 
     $arptStatusCode, $arptCert, 
     $naspAgreementCode, $arptAirspcAnalysed, $aoe, $custLandRights, 
     $militaryJoint, $militaryRights, $nationalEmergency, $milUse, 
     $inspMeth, $inspAgency, $lastInsp, $lastInfo, $fuel, $airframeRepairs 
, 
     $engineRepairs, $bottledOyxgen, $bulkOxygen, 
     $lightingSchedule, $tower, $unicomFreqs, $ctafFreq, $segmentedCircle, 
     $lens, $landingFee, $isMedical, 
     $numBasedSEL, $numBasedMEL, $numBasedJet, 
     $numBasedHelo, $numBasedGliders, $numBasedMilitary, 
     $numBasedUltraLight, 
     $numScheduledOperation, $numCommuter, $numAirTaxi, 
     $numGAlocal, $numGAItinerant, 
     $numMil, $countEndingDate, 
     $aptPosSrc, $aptPosSrcDate, $aptElevSrc, $aptElevSrcDate, 
     $contractFuel, $transientStorage, $otherServices, $windIndicator, 
     $icaoId) = 
     unpack("A3 A11 A13 A4 A10 A3 A4 A2 A20 A21 A2 A40 " . 
     "A42 A2 A2 A35 A72 A45 A16 A35 A72 A45 A16 A15 A12 A15 A12 A1 A5 A1 " . 
     "A3 A4 A4 A30 A2 A3 A5 A4 A3 A30 A4 A3 A30 A1 A4 A30 A16 A16 " . 
     "A4 A30 A16 A4 " . 
     "A1 A7 A2 A15 A7 A13 A1 A1 A1 A1 A18 A6 A2 A1 A8 A8 A40 A5 A5 A8 " . 
     "A8 A9 A1 A42 A7 A4 A3 A1 A1 A3 A3 A3 A3 A3 A3 A3 " . 
     "A6 A6 A6 A6 A6 A6 A10" . 
     "A16 A10 A16 A10 A1 A12 A71 A3 A7", $line);