Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I use the sort function to order an array of filenames alphabetically; for example:

@names = ( "FLY_ABC123_01.jpg", "PG_ABC123_03", "SPL_ABC123_02.jpg" );

The normal sort function can return the files in ascending alphabetical order, which would be: FLY_ABC123_01.jpg, PG_ABC123_03.jpg, SPL_ABC123_02.jpg.

However, I would like to sort these filenames based on the number after the last underscore (e.g. "_01"). Is there any way to do this?

I guess one option would be to ignore the characters before the first underscore (e.g. "FLY_").

Thanks,
Ralph

Replies are listed 'Best First'.
Re: Sorting filenames with custom function
by kennethk (Abbot) on May 13, 2010 at 18:57 UTC
      ... I would like to sort these filenames based on the number after the last underscore ...

      This implies the OPer wants a numeric comparison of an extracted set of digits, so the  <=> (also in Equality Operators; see perlop) numeric comparator would be appropriate here.

        But the numbers presented are zero-padded integers, so the comparison is equivalent. If the numeric comparator were used with the simple split, a non-numeric comparison warning will be thrown (he does have warnings on, right?). Not all files listed have the .jpg file extension, so (split /_|\./, $a)[-2] won't work. I was also trying to keep it short/simple, preventing a long code block and making it easier for the OP to build his own. The best I came up with for using the numeric comparator sorted based upon the last block of digits:

        my $re = qr/\d+/; print join "\n", sort {($a =~ /$re/g)[-1] <=> ($b =~ /$re/g)[-1]; } @n +ames

        But then I'd have to link to perlretut and Regexp Quote Like Operators as well...

Re: Sorting filenames with custom function
by AR (Friar) on May 13, 2010 at 18:50 UTC

    Absolutely. You can use any function you can write. Check out the perldoc on sort.

    Give it a try, and if you're still having trouble, show us what went wrong and we'll be glad to help you.

Re: Sorting filenames with custom function
by Marshall (Canon) on May 13, 2010 at 22:17 UTC
    The real "trick" is to get the regex right that extracts the values from $a and $b. One way is:

    #!/usr/bin/perl -w use strict; my @names = qw( FLY_ABC123_01.jpg PG_ABC123_03.jpg SPL_ABC123_02.jpg ); @names = sort{ (my $A) = ($a =~ /.*_(\w+)/); (my $B) = ($b =~ /.*_(\w+)/); $A <=> $B }@names; print "@names"; #prints: FLY_ABC123_01.jpg SPL_ABC123_02.jpg PG_ABC123_03.jpg
    Update:(\d+) is fine here instead of (\w+) as per suggestion from AnomalousMonk
Re: Sorting filenames with custom function
by Anonymous Monk on May 14, 2010 at 18:37 UTC
    Thanks for all of your replies. Thanks Marshall for the regex, it works perfect and really helped me - since this is not my specialty. - Ralph