print for map{ m[(^\d+\s+(?:[\d\.]+\s+){3})(.+$)] } ; ## Outputs stuff like 0 622.7 319.1 303.6 50 530.6 265.9 264.6 1 618.0 316.8 301.2 51 548.1 274.9 273.2 ... 42 530.6 267.3 263.2 Under 16 10,490.0 5,380.2 5,109.7 44 569.0 286.1 282.9 Under 18 12,130.5 6,223.6 5,906.9 46 558.8 281.7 277.0 45-64/59* 9,614.5 5,450.5 4,164.0 48 542.6 273.2 269.5 65/60** 8,993.0 2,947.2 6,045.7 49 526.8 264.7 262.2 and over #### print for grep{ m[^\d+\s] } map{ m[(^\d+\s+(?:[\d\.]+\s+){3})(.+$)] } ; #### print for sort { local $^W; $a <=> $b } grep{ m[^\d+\s] } map{ m[(^\d+\s+(?:[\d\.]+\s+){3})(.+$)] } ; #### #! perl -slw use strict; my @lines = ; ## Split lines that fit the two column pattern into two my @data = map{ m[(^\d+\s+(?:[\d\.]+\s+){3})(.+$)] } @lines; ## Remove any lines that don't fit the pattern my @filtered = grep{ m[^\d+\s] } @data; ## Sort the lines by age my @sorted = sort { local $^W; ## Ignoring non-numeric warnings $a <=> $b } @filtered; ## And strip out the combined total. @trimmed = map{ s[(^\d+\s+)[\d\.]+\s+][$1]; $_; } @sorted; print "Age\tMale\tFemale"; printf for @trimmed; #### my( $age90line ) = grep{ m[90\s+and\s+over] } @lines; $age90line = join "\t", $age90line =~ m[(90\s+and\s+over)\s+\S+\s+(\S+)\s+(\S+)]; #### ## And strip out the combined total and add "Age end" my @trimmed = map{ s[(^\d+\s+)[\d\.]+\s+][$1\t$1]; $_; } @sorted; #### print "Age start\tAge end\tMale\tFemale"; print for @trimmed, $age90line; #### P:\test>501023-2 Age start Age end Male Female 0 0 319.1 303.6 1 1 316.8 301.2 2 2 321.6 306.8 ... 86 86 24.0 72.6 87 87 19.2 61.6 88 88 15.2 50.9 89 89 11.6 40.7 90 and over 31.8 131.3 #### print "Age start\tAge end\tMale\tFemale"; printf "%s\t\t%s\t\t%s\t\t%s\n", m[(\S+)\s*(\S+)\s+(\S+)\s+(\S+) for @trimmed, $age90line;