Perl Sort Hash by Value

Problem

Given a log file similar to Linux syslog format as in the following example:

Jan 4 03:15:01 pla kernel:pla: Some error message

Write a Perl script to print the top 5 most repeated error messages.

Solution

Read the file line by line then split each line using ":" as separator then use the error message token as the key in a hash table and the error message count as the corresponding hash value. At the end you will get all error messages and their counts stored in the hash table. After that you need to sort the hash table by value not by key in decreasing order. The final step is to loop through the hash and print the first 5 values.

Code

Here is the code in Perl

  1. #!/perl/bin/perl
  2.  
  3. # Command line arguments
  4. my $Args = "@ARGV";
  5.  
  6. # log file name
  7. if ($Args =~ /--log (S+)/)
  8. {
  9. $log = $1;
  10. }
  11.  
  12. # Hardcoded for testing purpose only
  13. $log = "/perl/test/Log.txt";
  14.  
  15. # Check tool usage
  16. if (!(defined($log)))
  17. {
  18. print "\n";
  19. print "Usage: question_two.pl [--log ]\n";
  20. print "\n";
  21. }
  22.  
  23. print "Please wait...\n\n";
  24.  
  25. # Open file for reading
  26. open (F, $log) or die "can not open file: $!";
  27.  
  28. # Hash table:
  29. # key: log message
  30. # value: count
  31. my %MessageCount = ();
  32.  
  33. # While there are lines to read
  34. while ()
  35. {
  36. # Remove EOL
  37. chomp($_);
  38.  
  39. # Split current line into tokens
  40. # using : as separator
  41. # Message is token 5
  42. @tokens = split(/:/, $_);
  43.  
  44. # Hash message while incrementing
  45. # its counter
  46. $MessageCount{$tokens[4]}++;
  47. }
  48.  
  49. # Close file
  50. close(F);
  51.  
  52. # Counter to 5
  53. my $i = 0;
  54.  
  55. # Sort hash by value (recall: not by key)
  56. foreach $key (sort{$MessageCount {$b} <=> $MessageCount {$a}} keys %MessageCount)
  57. {
  58. $i++;
  59.  
  60. print "$key : $MessageCount{$key}\n";
  61.  
  62. # Exit after printing the 5th most repeated message
  63. if ($i == 5)
  64. {
  65. last;
  66. }
  67. }
  68.  
Search Terms...

Leave a Reply