Solved

Perl sort question inside of a for loop

Posted on 2016-11-21
10
68 Views
Last Modified: 2017-01-17
I'm trying to sort a list of data that I'm reading from a file and putting inside of an array. I want to sort the data by date and status.  I'm having trouble sorting because I think there's nothing to compare so it just spits it out as it's read.  I don't know if I need to pass the data somewhere first before I'm able to sort it or finish the loop then sort it. In any case, please help and let me know if you need more clarification.

Thanks!

.....

for my $i ("01" .. "30") {
        `download files`;
        open(my $fh, '< ', $download_path.'/'.$file.'-'.$i) or die("Could not open file $file-$i: $!.");

        while (my @row = <$fh>) {
                chomp @row;
                @arr = split ' ', $row[0];
        }

        my ($date, $path, $level, $num, $status) = @arr[2,4,7,8,9];
        my @pop_path = split '/', $first[4];
        my $title = $pop_path[3];
        my $day = UnixDate($date, "%Y-%m-%d %H:%M:%S");

        @sorted = (
        {
                date => $day,
                title => $title,
                path => $path,
                level => $level,
                num => $num,
                status => $status,
        }
        );

        @sorted = sort {
                $b->{date} cmp $a->{date}
        } @sorted;

        foreach my $line (@sorted){
                printf "%-22s %-15s %-4s %-2s %-5s %-30s\n" => @{$line}{qw(date title level num status path)};
        }

        close($fh);
}

.....
0
Comment
Question by:akatsuki27
  • 4
  • 4
  • 2
10 Comments
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896789
As you are just using standard date stamps, you could use a simple utility such as 'sort' on linux or cygwin to do a multi column sort. Or import your file to something like Excel and do a multi column sort there.
0
 
LVL 28

Expert Comment

by:FishMonger
ID: 41896792
Your code has a number of problems, but instead of rewriting your code I'll point you to a youtube video of a YAPC talk about the use of map, grep and sort.  The sort portion of the talk gives at least one example of sorting by date fields.
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896856
Can you supply a sample of your input file? I think this could be solved with a sort one-liner if that's any help.
0
 

Author Comment

by:akatsuki27
ID: 41896951
Here's a sample of what's being read from the input:

20161113               title1       lev  1  comp  /some/path    
20161114               title2       lev  1  comp  /some/path  
20161115               title1       lev  2  comp  /some/path    
20161116               title1       lev  3  fail      /some/path

I want to be able to sort by date and then by status (5th column) if the date is the same. Does the sort need to be outside the loop or what?  I'm not an experienced coder, I just do small scripts like these for certain tasks so I'm sure there are probably cleaner ways to do this.
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41896998
If you are on Unix type system, you could just do this
sort -k1 -k5 input.txt > sorted.txt
Assuming you have spaces between columns. Use the -t option to specify another field delimiter.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:akatsuki27
ID: 41897615
If it's okay, can you suggest a solution using Perl? The sorting of the data is just one step to continue manipulating the data for another purpose. I just got stuck in that part of the script so I came here for some direction using Perl only, please.  Also, I'd rather not have to make too many system calls because I'm testing with a small amount of data.  Once the script is live, the amount of data processed will be huge and the script will be too taxing.  Btw, yes this will run on a *nix system.
0
 
LVL 28

Assisted Solution

by:FishMonger
FishMonger earned 500 total points
ID: 41898015
Did your watch the youtube video I pointed you to?

Instead of manually writing the sorting code our selves as shown in the video, we could use one of the soting modules on cpan.
Sort::Fields
#!/usr/bin/perl

use warnings;
use strict;
use Sort::Fields;
use Data::Dumper;

chomp(my @unsorted = <DATA>);
my @sorted = fieldsort ['1n', 4], @unsorted;

print Dumper \@sorted;

__DATA__
20161114               title2       lev  1  comp  /some/path
20161113               title1       lev  1  comp  /some/path
20161116               title1       lev  3  fail  /some/path
20161115               title1       lev  2  comp  /some/path

Open in new window


c:\test>test.pl

$VAR1 = [
          '20161113               title1       lev  1  comp  /some/path',
          '20161114               title2       lev  1  comp  /some/path',
          '20161115               title1       lev  2  comp  /some/path',
          '20161116               title1       lev  3  fail  /some/path'
        ];

EDIT:
I didn't realize how old that module was (1998) until after I posted, so it's not the best choice, but it does work.  There are more up-to-date modules available, or you can write the sort code yourself, which is pretty easy.
0
 

Accepted Solution

by:
akatsuki27 earned 0 total points
ID: 41898058
Thanks, FishMonger.  Honestly, I only saw part of the video since it was late at night and it's close to an hour.  I will check it out completely later though because I'm interested in learning more Perl.

But I was able to figure it out by writing it out myself. I pushed the incoming data into an array and sorted the array outside of the for loop. I put the print statement outside the loop also. Not pretty but it's working. The change in bold below:

....
        my @temp = (
        {
                date => $day,
                title => $title,
                path => $path,
                level => $level,
                num => $num,
                status => $status,
        }
        );

       foreach my $line (@temp){
                push (@sorted, $line);
        }


        close($fh);
}

@sorted = sort {  
        $a->{lnum} cmp $b->{num} ||
        $b->{date} <=> $a->{date}
} @sorted;

foreach my $sort (@sorted){
        printf "%-22s %-15s %-4s %-2s %-5s %-30s\n" => @{$sort}{qw(date title level num status path)};
}

.....
0
 
LVL 19

Expert Comment

by:Kim Ryan
ID: 41898500
Glad you worked out a Perl solution. You can also use awk, it's well suited to this type of problem?
0
 

Author Closing Comment

by:akatsuki27
ID: 41902982
I wasn't given a satisfactory answer before I figured it out on my own.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now