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

20120824/ABC/input/daily/11337111.xml 20120710/ABC/input/daily/11337101.xml 20120330/ABC/input/daily/11337111.xml 20130614/ABC/input/daily/11337890.xml 20130120/ABC/input/daily/11337111.xml 20120206/ABC/input/daily/11337111.xml 20121005/ABC/input/daily/11337890.xml 20130110/ABC/input/daily/11337111.xml 20120923/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20120404/ABC/input/daily/11337111.xml 20130211/ABC/input/daily/11337111.xml

This is the input file. Please tell me for a particular file, latest value in the first directory should match.

#!/usr/bin/perl open(INFO,"$ARGV[0]"); @array=<INFO>; close (INFO); @sortedarray=sort(@array); foreach $line(@sortedarray){ print "$line"; }

Example: output should be

20130211/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20130614/ABC/input/daily/11337890.xml

Replies are listed 'Best First'.
Re: sort based on last and first value
by kcott (Archbishop) on Aug 26, 2013 at 10:56 UTC

    Here's how you can extract the data you want and output it in the sort order you show:

    $ perl -Mstrict -Mwarnings -le ' my @xml_paths = qw{ 20120824/ABC/input/daily/11337111.xml 20120710/ABC/input/daily/11337101.xml 20120330/ABC/input/daily/11337111.xml 20130614/ABC/input/daily/11337890.xml 20130120/ABC/input/daily/11337111.xml 20120206/ABC/input/daily/11337111.xml 20121005/ABC/input/daily/11337890.xml 20130110/ABC/input/daily/11337111.xml 20120923/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20120404/ABC/input/daily/11337111.xml 20130211/ABC/input/daily/11337111.xml }; my %latest; for (@xml_paths) { m{(.+\/)([^\/]+)}; $latest{$2} = $1 if ! $latest{$2} || ($latest{$2} cmp $1) < 0; } print for sort map { "$latest{$_}$_" } keys %latest; ' 20130211/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20130614/ABC/input/daily/11337890.xml

    You're still going to have to read your data from a file. Using the code you've posted will cause you no end of problems, particularly when you write scripts of more than half a dozen lines. I recommend you change:

    #!/usr/bin/perl open(INFO,"$ARGV[0]"); @array=<INFO>; close (INFO)

    To something closer to this:

    #!/usr/bin/perl use strict; use warnings; use autodie; open my $input_fh, '<', $ARGV[0]; my @xml_paths = <$input_fh>; close $input_fh;

    "@array" is a completely meaningless variable name: the "@" already tells us it's an array; "array" adds nothing useful. "@xml_paths", on the other hand, gives a pretty clear indication of what it is (even when it appears many lines later after "my @xml_paths = <$input_fh>;" has scrolled off the top of the screen).

    For the other recommended changes, see strict, warnings, autodie and open.

    If you want to write your own custom die messages, such as those shown in the open documentation, you don't need the "use autodie; line; however, if you do this, make sure you've checked the results of all the functions that autodie checks and written custom messages for all of them. Obviously, using the autodie pragma is a lot less work for you.

    -- Ken

Re: sort based on last and first value
by 2teez (Vicar) on Aug 26, 2013 at 11:02 UTC

    Hi, I really don't understand what you want but from, your desired output, I suppose you want to sort your files in the directory which has the same names ( about three files names with different date tags ), but different date tag.
    Then get the latest of these files based on the date.
    If an right, this is one way of doing that.

    use warnings; use strict; my %report = map { $_->[2] => $_->[0] } sort { $a->[1] <=> $b->[1] || $b->[2] <=> $a->[2] } map { [ $_, /^(\d+?)\/.+\/(\d+?)\./ ] } <DATA>; print $report{$_}, $/ for reverse keys %report; __DATA__ 20120824/ABC/input/daily/11337111.xml 20120710/ABC/input/daily/11337101.xml 20120330/ABC/input/daily/11337111.xml 20130614/ABC/input/daily/11337890.xml 20130120/ABC/input/daily/11337111.xml 20120206/ABC/input/daily/11337111.xml 20121005/ABC/input/daily/11337890.xml 20130110/ABC/input/daily/11337111.xml 20120923/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20120404/ABC/input/daily/11337111.xml 20130211/ABC/input/daily/11337111.xml
    produces...
    20130211/ABC/input/daily/11337111.xml 20130416/ABC/input/daily/11337101.xml 20130614/ABC/input/daily/11337890.xml

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: sort based on last and first value
by hdb (Monsignor) on Aug 26, 2013 at 11:07 UTC

    As a one-liner:

    print values { map { (/\/(\d+)\./)[0] => $_ } sort <DATA> };
      just as I was arduously composing this, which does roughly the same:
      my %latest; for (sort <INFO>) { # by date my ($date, $path) = split "/", $_, 2; # assuming these are compl +ete paths $latest{$path} = $_; # newer overwrites older } # output ordered by "path" values print $latest{$_} for sort keys %latest;
Re: sort based on last and first value
by Corion (Patriarch) on Aug 26, 2013 at 10:17 UTC

    Where is the actual problem you have?