Most Recent Blog

King's View of the Battle

 Open GL model of a chess board.

Showing posts with label multi line. Show all posts
Showing posts with label multi line. Show all posts

June 1, 2012

Eclipse/NetBeans Multi Line Search and Replace Across Files

We all know System.out.println statements are not good for performance and clutter logs.  We should use a logger instead.  Loggers allow for the control of logging levels.  How do you replace these System.outs in a large project?  Here are the steps used recently:
  1. Come up with a good REGular EXspresion (REGEX), for matching your desired code.
  2. Come up with your replacement regex and capture user.
  3. Ensure that your code compiles and inspect your changes.
In this case we want to replace the following:
package com.ecokrypt...

public class ToManySystemOuts {

    System.out.println("Single Line System.out.println");


    System.out.println("Rare multiline " +
           " System.out.println ");

}
We need to find a REGEX that will match both of these cases.  There are several ways to do any REGEX, but a solution that is easy  to understand that will work is:

   (?s)System.out.println(\(([^;]+?)\));

We have to dissect what this is saying to understand a couple of subtleties:
  • (?s) - indicates that we search past line feeds.  Without this we will not match the second case because the line feed would cause the REGEX to not match at all.
  • System.out.println - matches the exact phrase
  • (\(([^;]+?)\)) - is very complicated, and will take time before you can read this.  A technique that typically works is to read it inside out.  Trying that out:
    • [^;]+ - look for anything that is NOT a ';' (semicolon).  the + is saying that you have to match at least 1, and there is no limit to how many characters you can match.
    • ([^;]+?) - Has a real subtlety to it, Regexes have an ability to be greedy, or lazy.  A greedy regex will match the largest region it can.  A lazy regex will match the smallest area it can.  It will take time to figure out when to use which, but the basic advice given here is ALWAYS try to use lazy.  Only use greedy if you really need it.  This REGEX is obviously lazy, how can you tell?  Think about it a bit.
      • the ? indicates that you are going to look for the next sequence imediately after.  
      • the (...) indicates you are going to "capture" whatever you find presumably for later use.
      • therefore the ( ) are not matched but are just part of the regex capture syntax.
      • So the answer is: if the ? is inside the capture group e.g. (...?) the matching is lazy; if the ? is outside of the capture group, the matching is greedy e.g. (...)?
    • \(([^;]+?)\)  - says, adds the \(...\) to the previous the \ is an escape character and says match a ( and a ), don't create another capture group.
    • (\(...\)) - says, now add another capture group containing everything inside the literals ( ).
  • ; the semicolon at the end says match a literal semicolon.
That is pretty much all there is to it.  Look at the following REGEX, which might be a common mistake and see if you can figure out why it won't work.  Guess what it will match.  (HINT thing about greedy vs lazy).

   (?s)System.out.println(\(([^;]+)?\));

Now that we have our matching REGEX, we need to get our replacement REGEX:

   System.out.println$1;

This is much simpler, it says:  replace the above match, with logger.debug$1; where $1 is inclusive the literal (...).  e.g. the braces and everything inside of them.

How do we do this inside of Eclipse or NetBeans?
I find NetBeans to be much nicer in some respects, and not so nice in others.


NetBeans in File Search Replace
This is the netbeans view, it uses the space very nicely and there is NO POPUPS...  You really have to like the ergonomics of NetBeans.  The search is dynamic and nicely highlighted so you can see the search as you go.
NetBeans Replace Across All Files
USE CRTL-H for a shortcut to this Menu.

NetBeans Confirmation Dialog

Eclipse:

The Eclipse Search Dialog.  (Allows you to select scope)