Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Sorting hash values

by K_M_McMahon (Hermit)
on May 23, 2005 at 05:26 UTC ( [id://459449]=perlquestion: print w/replies, xml ) Need Help??

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

Hello fellow Monks. I am sure there is a simple (and obvious) answer to this question that I am just overlooking. Thanx for any help you can give me would be great!

I threw together a script to scan through my linux message log to track the failed login attempts. I was trying to see which IP addresses were responsible for most of the attempts. (also which usernames were tried multiple times). I created a hash to store the IP address as the key and the times found as the count. How do I get the results sorted by frequency. I don't know how to sort by the value, and I can't make the count the key because it is not unique.

I tried pushing the result strings into an array which I can sort if the number is first, but that failed to sort properly since I can't use {$a<=>$b} because of the text!
#!/usr/bin/perl -w use strict; my ($attempt,$failed)=(0,0); my (%ip,%usr); opendir(TEMP,'.') or die "I can't open the current directory.\n"; my @files=grep(/^messages/,readdir(TEMP)); closedir(TEMP); foreach my $file (@files) { print "Found $file\n"; &check($file); } print "Found $attempt intrustion attempts.\n"; print "Found ($failed) failed matches.\n"; foreach my $key (keys(%ip)) { print "Found $ip{$key} attempts from $key\n"; } foreach my $key (keys(%usr)) { print "Found $usr{$key} attempts for $key.\n"; } sub check { my $file=shift; open(LOG,"<$file") or die "Can't open $file\n"; while (<LOG>) { next if $_!~m/Failed/; $attempt++; my ($username,$ip_no)=$_=~/Failed .* for (?:illegal user )?(\w ++-?\w*) from ::[a-f0-9]{4}:(\d+\.\d+\.\d+\.\d+)/; if ((defined($username))&&(defined($ip_no))) { $ip{$ip_no}++; $usr{$username}++; } else {$failed++; } } close(LOG); }

What obvious solution am I missing?


-Kevin
my $a='62696c6c77667269656e6440676d61696c2e636f6d'; while ($a=~m/(^.{2})/s) {print unpack('A',pack('H*',"$1"));$a=~s/^.{2}//s;}

Replies are listed 'Best First'.
Re: Sorting hash values
by davido (Cardinal) on May 23, 2005 at 05:34 UTC

    You wish to sort a list of hash keys in order by the values they index. Try this:

    my @ips_prioritized = sort { $ip{$a} <=> $ip{$b} } keys %ip;

    Dave

Re: Sorting hash values
by Zaxo (Archbishop) on May 23, 2005 at 05:36 UTC

    You can sort the keys by value in the hash:

    my @ips = sort { $ip{$b} <=> $ip{$a} } keys %ip; my @usrs = sort {$usr{$b} <=> $usr{$a}} keys %usr;
    By comparing $b terms on the left, we get descending order.

    After Compline,
    Zaxo

Re: Sorting hash values
by K_M_McMahon (Hermit) on May 23, 2005 at 05:42 UTC
    Thanx davido && zaxo, I knew it was something simple!

    -Kevin
    my $a='62696c6c77667269656e6440676d61696c2e636f6d'; while ($a=~m/(^.{2})/s) {print unpack('A',pack('H*',"$1"));$a=~s/^.{2}//s;}

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://459449]
Approved by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (1)
As of 2025-01-13 10:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which URL do you most often use to access this site?












    Results (28 votes). Check out past polls.