use strict; my $datafields = 3; my $item_no = 2; my @records; # read from DATA - any filehandle will do . . . foreach my $line () { chomp $line; push @records, [ split(/\s+/,$line,$datafields) ]; } =comment now @records looks like this: @records = ( ['foo','gabba','12'], ['bar','hey','2'], ['baz','gabba','38'] ); the elements in []'s are array references now store the array references based on the order of the 3rd element, which is a number - numbers are compared with the <=> operator, strings are comparted with the cmp operator - $a and $b are magic variables that contain the two items being compared - if you want ascending order, compare $a to $b - for descencing order, compare $b to $a =cut my @sorted = sort { $b->[$item_no] <=> $a->[$item_no] } @records; =comment that's it! now print out the results - the tricky part is that @sorted is a list of list REFERENCES, so we need to do some extra work to de-reference them =cut foreach my $line (@sorted) { print join(', ', @$line), "\n"; } =comment the following would normally be found in a data file. i originally delimited these values with tabs, but they will probably turn into spaces when you copy and paste that's why i used /\s+/ instead of /\t/ in split above =cut __DATA__ foo gabba 12 bar hey 2 baz gabba 38