/ / Przetwarzaj pliki o stałej szerokości - perl, parsowanie

Parsuj pliki o stałej szerokości - perl, parsowanie

Mam wiele plików tekstowych z polami o stałej szerokości:

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

Pozostałe pliki są w podobnym formacie, gdzie <c> zaznaczy początek kolumny, ale mają różne (nieznane) szerokości kolumn i przestrzeni. Jaki jest najlepszy sposób analizowania tych plików?

Próbowałem użyć Text::CSV, ale ponieważ nie ma ogranicznika, trudno jest uzyskać spójny wynik (chyba, że ​​użyję modułu nieprawidłowo):

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

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

Odpowiedzi:

12 dla odpowiedzi № 1

Jak wspomina użytkownik604939, unpack jest narzędziem używanym dla pól o stałej szerokości. Jednak, unpack musi zostać przekazany szablon do pracy. Ponieważ mówisz, że Twoje pola mogą zmieniać szerokość, rozwiązaniem jest zbudowanie tego szablonu z pierwszego wiersza 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: $templaten";

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óry drukuje:

szablon: A8 A10 A * $ VAR1 = [ [ „Dave”, "Tomasz", „123 Główny” ], [ „Dan”, „Anderson”, „456 Center” ], [ „Wilma”, "Tęcza", „789 Street” ] ];

6 dla odpowiedzi nr 2

CPAN na ratunek!

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


3 dla odpowiedzi nr 3

Po prostu użyj Perla rozpakować funkcjonować. Coś takiego:

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

<Do something ....>
}

Wewnątrz szablonu rozpakowującego można „A ###”wstaw szerokość pola dla każdego A. Istnieje wiele innych formatów, których można używać do łączenia i dopasowywania, czyli pól liczb całkowitych itp. Jeśli plik ma stałą szerokość, podobnie jak pliki mainframe, powinno to być najłatwiejsze.