Hej Bjarne.
Bjarne Jensen wrote:
> Det ku'være interessant. Please go ahead!
Det tog lidt længere tid end forventet, men det var da skægt at lave.
Dette script laver en liste af forslag til mulige record-længder for en
given datafil.
Bemærk at scriptets køretid er O(n^2), så hvis du giver det en meget
stor datafil, bliver det aldrig færdigt. Du kan med fordel fodre
programmet med et udsnit der starter i starten af det datasæt, du vil
undersøge. Hvis der er sikkerhed for at datafilen altid indeholder et
helt antal records (at det ikke slutter i midten af en record), kan man
skrive det om til at køre i ca. O(n log(n)) hvilket er en del hurtigere.
Man kan også lave en eller anden adaptiv søgning, så scriptet selv kan
regne ud hvornår det skal holde op med at lede, men det må komme i en
senere version...
Derudover kan man også udvide scriptet til at finde kolonner, men det
resultat man så ville få, er en del mere usikkert, så det har jeg
droppet indtil videre.
Syntaks: recsize.pl < datafil
Output: første tal i hver række er et forslag til en record-størrelse og
andet tal er hvor godt den størrelse passer (højt tal ~ passer godt).
Mvh. Michael.
--- recsize.pl begynder her ---
#!/usr/bin/perl
# Find possible record sizes of data files with fixed size records and
# no record separators.
# Author: Michael Zedeler.
# Method:
# For each candidate record size:
# Set initial candidate record size score to zero.
# Traverse data column by column:
# Find size of vertical columns of spaces
# Each vertical column of space contributes with its height squared
# to the score of the given candidate record size.
# Print candidate record size and log10 of score.
#
# The highest scoring record size candidates are the ones that are
# most likely to be correct.
use warnings;
$/ = undef;
my @data = grep { $_ !~ /[\r\n]/} split //, <STDIN>;
my $data_length = @data;
my @scores;
foreach $record_length ( 3 .. $data_length ) {
my $records = int($data_length/$record_length);
my $score = 0;
my $height = 0;
for( my $i = 0; $i < $records * $record_length; $i++ ) {
# Traverse data column by column
my $row = $i % $records;
my $column = int( $i / $records );
my $char = $data[$row * $record_length + $column];
$height++ if( $char eq ' ');
# Add score of vertical space if we see another char or at end
# of column
if( $row == $records or $char ne ' ' ) {
$score += $height ** 2;
$height = 0;
}
}
# We may have missed a final score if last char was a space
$score += $height ** 2;
$score = log($score)/log(10);
print "$record_length: $score\n";
}