Java Matcher's QuoteReplacement() And Java 6 vs. Java 1.4.2

Posted January 25, 2010 at 8:36 AM by Ben Nadel

Tags: ColdFusion

Last week, on a very old post about the importance of escaping the "$" and "\" characters in appendReplacement() calls on the Java Pattern Matcher, Rob asked me why I wasn't just using the quoteReplacement() method. To be honest, I had never seen this method before. After a quick Google search, I found that this method will escape your replacement text in such a way that none of its characters will hold any special meaning. Typically, if you have a "$" in your replacement text, the Matcher is expecting it to be followed by a numeric value in reference to a captured group. The "\", on the other hand, is expected to be escaping characters. To stop the Matcher from performing such evaluation, you can pass your replacement text through the intermediary method call, quoteReplacement():

  • <!--- Store some text to search / replace. --->
  • <cfset text = "Let's make some cash money." />
  •  
  • <!--- Create the pattern we are going to search form. --->
  • <cfset pattern = createObject( "java", "java.util.regex.Pattern" )
  • .compile(
  • javaCast( "string", "money" )
  • )
  • />
  •  
  • <!--- Create our pattern matcher based on the target text. --->
  • <cfset matcher = pattern.matcher(
  • javaCast( "string", text )
  • ) />
  •  
  • <!--- Create a string buffer to hold our replacement text. --->
  • <cfset buffer = createObject( "java", "java.lang.StringBuffer" )
  • .init()
  • />
  •  
  • <!---
  • While we can find matches for "money", let's replace them
  • with the dollar sign.
  • --->
  • <cfloop condition="matcher.find()">
  •  
  • <!---
  • Replace with $. Notice that we are passing the
  • replacement text through the quoteReplacement()
  • method; this will escape special characters like
  • the "$" and "\".
  • --->
  • <cfset matcher.appendReplacement(
  • buffer,
  • matcher.quoteReplacement( javaCast( "string", "$" ) )
  • ) />
  •  
  • </cfloop>
  •  
  • <!--- Add the rest of the target string to the buffer. --->
  • <cfset matcher.appendTail( buffer ) />
  •  
  • <!--- Output the full replacement. --->
  • Result: #buffer.toString()#

As you can see, we are using a round-about way (for demo purposes) to replace the pattern, "money," with the string, "$". As we perform the replacement, we pass our replacement string through the quoteReplacement() method; and, when we run the above code, we get the following output:

Result: Let's make some cash $.

If we did not use quoteReplacement(), the Java Matcher would have expected a captured group reference and would have thrown the following error:

String index out of range: 1 null

This is a pretty convenient method and it makes me frustrated that I had never seen it before, especially since I've used the Matcher object so many times. At first, I thought it was just laziness in my exploration of the Matcher API; but, this morning, when I went to find it again, I realized what happened. As I started to write this post, I did a Google search for "java 2 matcher" in order to look at the method definition. This search got me to the Matcher documentation for Java 1.4.2 - the one I usually use. Low and behold, there was no quoteReplacement() method!

At first, I thought I was going crazy! How was it here last week and not this week? Then it dawned on me: ColdFusion now uses the newer JVM with Java 6. For the past few years, I've been explicitly searching for the Java 2 docs to make sure that the docs were the first Google search results. That was fine years ago when I started, but now, I'm 2 Java versions behind on my research and development! Shame shame! It looks like a good deal has been added to the API in the last few versions.

A big thanks to Rob for not only pointing out a useful Java Matcher method - quoteReplacement() - but also for making me realize how out of date my Java research actually was. Looks like it's time to catch up on what's new in the Java language.




Reader Comments

Jan 25, 2010 at 9:05 AM // reply »
148 Comments

More blog fodder!


Jan 25, 2010 at 9:06 AM // reply »
11,243 Comments

@Lola,

I hope so :)


Rob
Jan 25, 2010 at 5:20 PM // reply »
3 Comments

/thumbsup


Jan 25, 2010 at 5:21 PM // reply »
11,243 Comments

@Rob,

Thanks again Rob :)


Sep 23, 2010 at 12:37 AM // reply »
1 Comments

Just wanted to say thanks for posting this! I came across this today and it has been a great help :)

Thanks again!


Sep 23, 2010 at 2:30 PM // reply »
11,243 Comments

@Evan,

Cool - glad to help. Now, when I look things up on the Java docs, I always make it a point to Google "Java 6" when I do my searching.


Feb 23, 2011 at 8:07 AM // reply »
1 Comments

How crazy is that. I had the exact same issue and the quoteReplace solved the issue.
I myself also have never seen or heard about this method - seems that it was not needed with java 1.4.x but only with recent versions ie. >=1.5.

But thanx for painting a clear picture!


Feb 23, 2011 at 10:38 AM // reply »
11,243 Comments

@Morten,

My pleasure! It looks like when you Google for anything doc-related to Java, the 1.4.2 library seems to be the thing you get. Makes me wonder how much juiciness I've been missing out on!


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 23, 2013 at 11:06 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Are you talking about As Number: YES As String: YES As Java: YES? If so, that's with 3 different ways of referencing the constant 1, not users.id[1]. Query object references(*) are what seem ... read »
May 23, 2013 at 9:55 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dan, According to the CF Admin, I'm running Java "1.6.0_45". As far as the DB column, in the database it's an INT. I'll see if I can dig into what CF sees it as. @WebManWalking, But h ... read »
May 23, 2013 at 9:49 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, I think the problem is that we're used to loose typing in ColdFusion, like JavaScript. If a value is a number but it's needed in an expression to be a string, noooo problem. I've encountered ... read »
May 23, 2013 at 9:47 AM
ColdFusion QueryAppend( qOne, qTwo )
You rock! Thank you, thank you, thank you!!! ... read »
May 23, 2013 at 5:19 AM
Ask Ben: Print Part Of A Web Page With jQuery
How to print also the background color of table cells and table lines ... read »
May 23, 2013 at 3:55 AM
Javascript Array Methods: Unshift(), Shift(), Push(), And Pop()
very interesting and helpful too. ... read »
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools