sub smart_sort { my @a = lc($a) =~ /(\d+|[a-z]+)/ig; # better split on fields my @b = lc($b) =~ /(\d+|[a-z]+)/ig; for my $i ( 0..(@a < @b ? $#a : $#b) ) { # try numbers first if ( $a[$i] =~ $NUMBER_ONLY_REGEX and $b[$i] =~ $NUMBER_ONLY_REGEX and $a[$i] <=> $b[$i] ) { return $a[$i] <=> $b[$i]; } # fallback to string compare if( $a[$i] cmp $b[$i] ) # no "elsif" { return $a[$i] cmp $b[$i]; } } # can't decide by fields, decide by whole string return $a cmp $b; }