2011-02-06 13 views
8

Mam wiele plików tekstowych z polami stałymi-width:pliki Parse stałej szerokości

<c>  <c>  <c> 
Dave Thomas 123 Main 
Dan  Anderson 456 Center 
Wilma Rainbow 789 Street 

Reszta plików są w podobnym formacie, gdzie <c> będzie początkiem kolumny, ale mają różne (nieznane) kolumny szerokości. Jaki jest najlepszy sposób na przeanalizowanie tych plików?

Próbowałem za pomocą Text::CSV, ale ponieważ nie ma ogranicznik trudno uzyskać spójny wynik (chyba Używam niewłaściwym Module):

my $csv = Text::CSV->new(); 
$csv->sep_char (' '); 

while (<FILE>){ 
    if ($csv->parse($_)) { 
     my @columns=$csv->fields(); 
     print $columns[1] . "\n"; 
    } 
} 
+1

Dlaczego nie zgadzasz się z tagiem "parsowanie"? To jest problem z parsowaniem. To, że potrzebujesz rozwiązania w Perlu, nie oznacza, że ​​nie jest to problem parsujący. – zwol

+0

ponieważ nie chcę ogólnego rozwiązania –

+0

może źle zrozumiałem ... Myślałem, że umieszczenie "parsowania" w tym przyniesie całą masę rozwiązań, które nie są istotne dla mojej sytuacji (np. Python, php, itp.) .. ..thx –

Odpowiedz

12

Jak podaje użytkownik user494939, narzędzie do stosowania w polach o stałej szerokości. Jednak unpack należy przekazać szablon do pracy. Skoro mówisz twoje pola może zmienić szerokość, rozwiązaniem jest zbudowanie tego szablonu z pierwszej linii pliku:

my @template = map {'A'.length}  # convert each to 'A##' 
       <DATA> =~ /(\S+\s*)/g; # split first line into segments 
$template[-1] = 'A*';     # set the last segment to be slurpy 

my $template = "@template"; 
print "template: $template\n"; 

my @data; 
while (<DATA>) { 
    push @data, [unpack $template, $_] 
} 

use Data::Dumper; 

print Dumper \@data; 

__DATA__ 
<c>  <c>  <c> 
Dave Thomas 123 Main 
Dan  Anderson 456 Center 
Wilma Rainbow 789 Street 

która drukuje:

 
template: A8 A10 A* 
$VAR1 = [ 
      [ 
      'Dave', 
      'Thomas', 
      '123 Main' 
      ], 
      [ 
      'Dan', 
      'Anderson', 
      '456 Center' 
      ], 
      [ 
      'Wilma', 
      'Rainbow', 
      '789 Street' 
      ] 
     ]; 
+0

@random_months_later_downvoter => czy chcesz powiedzieć, dlaczego? –

3

Wystarczy użyć unpack funkcji Perl. Coś takiego:

while (<FILE>) { 
    my ($first,$last,$street) = unpack("A9A25A50",$_); 

    <Do something ....> 
} 

Wewnątrz rozpakować szablon, pozycja „A ###”, które można umieścić szerokość pola dla każdej A. Istnieje wiele innych formatów, które można wykorzystać do mieszania i Dopasuj do, czyli do pól całkowitych, itd ... Jeśli plik ma ustaloną szerokość, podobnie jak pliki mainframe, powinno to być najprostsze.

+0

To część mojego pytania ... szerokość pola zmieni się w zależności od pliku, który go karmię. Czy istnieje sposób na rozpakowanie w celu wykrycia szerokości z nagłówka? –

6

CPAN na ratunek!

DataExtract::FixedWidth nie tylko analizuje pliki o stałej szerokości, ale (w oparciu o POD) wydaje się być na tyle sprytny, aby samodzielnie odczytać szerokości kolumn z linii nagłówka!

+0

+1 Odpowiedź zanotowana :-) –

+0

BTW, autor od czasu do czasu wisi na SO. – DVK

+0

DVK ++ =) dzięki! DE: FW jest również dobrze przetestowany z [tony wejścia testowego.] (Http://api.metacpan.org/source/ECARROLL/DataExtract-FixedWidth-0.09/t/data/) –

Powiązane problemy