title: perl Regular Expression to find Java StackTrace by keyword
body: <p>I need to grep full stacktrace from logfile by keyword.</p>
  
  <p>This code works fine, but to slow on big files (more than file the slower).
  I think the best way to improve regex to find keyword, but I could not get it done.</p>
  
  <hr>
  
  <pre><code>#!/usr/bin/perl
  
  use strict;
  use warnings;
  
  my $regexp;
  my $stacktrace;
  undef $/;
  
  $regexp = shift;
  $regexp = quotemeta($regexp);
  
  while (&lt;&gt;) {
    while ( $_ =~ /(?&lt;LEVEL&gt;^[E|W|D|I])\s
                   (?&lt;TIMESTAMP&gt;\d{6}\s\d{6}\.\d{3})\s
                   (?&lt;THREAD&gt;.*?)\/
                   (?&lt;CLASS&gt;.*?)\s-\s
                   (?&lt;MESSAGE&gt;.*?[\r|\n](?=^[[E|W|D|I]\s\d{6}\s\d{6}\.\d{3}]?))/gsmx ) {
      $stacktrace = $&amp;;
      if ( $+{MESSAGE} =~ /$regexp/ ) {
        print "$stacktrace";
      }
    }
  }
  </code></pre>
  
  <p>Usage: <code>./grep_log4j.pl &lt;pattern&gt; &lt;file&gt;</code></p>
  
  <p>Example: <code>./grep_log4j.pl Exception sample.log</code></p>
  
  <p>I think problem in <code>$stacktrace = $&amp;;</code> because if remove this string and simply print the all matching lines script works fast.
  Version of script to print all matches:</p>
  
  <pre><code>#!/usr/bin/perl
  
  use strict;
  use warnings;
  
  undef $/;
  
  while (&lt;&gt;) {
    while ( $_ =~ /(?&lt;LEVEL&gt;^[E|W|D|I])\s
                   (?&lt;TIMESTAMP&gt;\d{6}\s\d{6}\.\d{3})\s
                   (?&lt;THREAD&gt;.*?)\/
                   (?&lt;CLASS&gt;.*?)\s-\s
                   (?&lt;MESSAGE&gt;.*?[\r|\n](?=^[[E|W|D|I]\s\d{6}\s\d{6}\.\d{3}]?))/gsmx ) {
      print_result();
    }
  }
  
  sub print_result {
      print "LEVEL: $+{LEVEL}\n";
      print "TIMESTAMP: $+{TIMESTAMP}\n";
      print "THREAD: $+{THREAD}\n";
      print "CLASS: $+{CLASS}\n";
      print "MESSAGE: $+{MESSAGE}\n";
  }
  </code></pre>
  
  <p>Usage: <code>./grep_log4j.pl &lt;file&gt;</code></p>
  
  <p>Example: <code>./grep_log4j.pl sample.log</code></p>
  
  <p>Lo4j pattern: <code>%-1p %d %t/%c{1} - %m%n</code></p>
  
  <p>Example of logfile:</p>
  
  <pre><code>I 111012 141506.000 thread/class - Received message: something
  E 111012 141606.000 thread/class - Failed handling mobile request
  java.lang.NullPointerException
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
    at java.lang.Thread.run(Thread.java:619)
  W 111012 141706.000 thread/class - Received message: something
  E 111012 141806.000 thread/class - Failed with Exception
  java.lang.NullPointerException
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
    at java.lang.Thread.run(Thread.java:619)
  D 111012 141906.000 thread/class - Received message: something
  S 111012 142006.000 thread/class - Received message: something
  I 111012 142106.000 thread/class - Received message: something
  I 111013 142206.000 thread/class - Metrics:0/1
  </code></pre>
  
  <p>My regex you can find on <a href="http://gskinner.com/RegExr/" rel="nofollow">http://gskinner.com/RegExr/</a> by log4j keyword:</p>