# $example = 0; $debug = 0; $verbose = 0; $separator = ';'; $category_index = 0; $amount_index = 1; while (@ARGV+0 && $ARGV[0] =~ /^-/) { my $aa = $ARGV[0]; last if $aa eq '--'; if ($aa eq '--category_index') { $category_index = $ARGV[1]; die "category index must be a positive integer " if $category_index !~ /^\d+$/; shift @ARGV; shift @ARGV; } elsif ($aa eq '--amount_index') { $amount_index = $ARGV[1]; die "amount index must be a positive integer " if $amount_index !~ /^\d+$/; shift @ARGV; shift @ARGV; } elsif ($aa eq '--separator') { $sep = $ARGV[1]; if ($sep eq "space" || $sep eq " ") { $separator = ' '; } elsif ($sep eq "comma" || $sep eq ",") { $separator = ' '; } elsif ($sep eq "semicolon" || $sep eq ";") { $separator = ';'; } elsif ($sep eq "tab" || $sep eq "\t") { $separator = "\t"; } elsif ($sep eq "whitespace") { $separator = '\s+'; } else { die "unknown field separator type '$sep' "; } shift @ARGV; shift @ARGV; } elsif ($aa eq '-d') { $debug = 1; shift @ARGV; } elsif ($aa eq '-v') { $verbose = 1; shift @ARGV; } elsif ($aa eq '-e') { $example = 1; shift @ARGV; } else { die "unknown option '$aa'"; } } sub mygetline { if ($example) { return ; } else { return <>; } } while ($_ = &mygetline) { last if /^__END__/; next if /^#/; next if /^\s*$/; if (/^begin\s+target-ratios/) { while ($_ = &mygetline) { last if /^end\s+target-ratios/; next if /^#/; next if /^\s*$/; chomp; s/^\s+//; ($categ, $ratio) = split /[\s:=]+/; printf("line '$_', ratio '$ratio'\n") if $debug; $ratio = sprintf("%f",$ratio); $ratio = 0.000001 if ($ratio == 0.0); printf("category '%s' target ratio '%s', %f\n", $categ, $ratio) if $verbose; $target_ratio{$categ} = $ratio; } } elsif (/^totals/) { @kk = sort(keys %totals); if ($debug) { printf("printing %d categories\n", @kk+0); } $fsum=0; foreach $key (@kk) { $fraction = $totals{$key}/$total; $fsum += $fraction; printf("%s\t= %10.2f (%.3f)\n" , $key, $totals{$key}, $fraction ); } printf("total\t: %10.2f (%.3f)\n", $total, $fsum); %totals=(); $total = 0; next; } elsif (/^grand-totals/) { @kk = sort(keys %gtotals); printf("Grand totals for %d categories\n", @kk+0); $fsum=0; foreach $key (@kk) { $fraction = $gtotals{$key}/$gtotal; $fsum += $fraction; if (defined($ratio = $target_ratio{$key})) { $targ = $gtotal * $ratio; printf("%s\t= %10.2f (%.3f) plus %.2f = target %.2f (%.3f)\n" , $key, $gtotals{$key}, $fraction , $targ-$gtotals{$key} , $targ , $targ/$gtotal ); } else { printf("%s\t= %10.2f (%.3f)\n" , $key, $gtotals{$key}, $fraction ); } } printf("gtotal\t: %10.2f (%.3f)\n", $gtotal, $fsum); %gtotals=(); $gtotal = 0; next; } elsif (/^columns\s*(:|=)?\s/) { $remainder = $'; chomp $remainder; @headers = split $separator, $remainder; $index = 0; foreach $colname (@headers) { $colname =~ s/\s+//g; if ($colname =~ /amount/i) { $amount_index = $index; printf("amount index set to %d\n", $amount_index) if $verbose; } elsif ($colname =~ /category/i) { $category_index = $index; printf("category index set to %d\n", $category_index) if $verbose; } $index++; } next; } elsif (/^print\s/) { print $'; next; }; if ($_ !~ $separator) { if ($verbose) { print "ignoring line:$_"; } next; } chomp; @f = split $separator; if ($debug) { print STDERR @f+0, ' fields: ', (join '|', @f), "\n"; } #print '', (join '|', @f), "\n"; #($sym,$name,$sh,$pr,$t,$class) = @f; $class = $f[$category_index]; $class =~ s/\s//g; $t = $f[$amount_index]; $t =~ s/(\$|,|\s)//g; if ($verbose) { printf("category='%s', amt='%s'\n", $class, $t); } $totals{$class} += $t; $gtotals{$class} += $t; $total += $t; $gtotal += $t; } __DATA__ # # Here is the sample data, used if "-e" is given to script by # perl -e # # assign target ratios to each category # begin target-ratios dogs = 0.2 cats = 0.4 birds = 0.4 end target-ratios # # This is the first group of totals # print First Division dogs;1;1000 cats;2;2000 dogs;3;3000 birds;4;4000 birds;5;5000 this is junk totals # # Another group of totals. # In this group, we use different columns for category and amount. # print Second Division columns = category; junk; amount; junk dogs;junk1;1;11 cats;junk2;2;22 totals # # Print grand totals, with +/- amounts to reach targets # grand-totals __END__