The Regular Expression Multiline Flag In ColdFusion

Posted October 10, 2006 at 7:41 AM

Tags: ColdFusion

I am not sure how this applies directly to ColdFusion regular expressions and the use of REFind() and REReplace(). I have only tested this in the Java regular expressions that are available through ColdFusion (Once you go Java you can't go back). In standard regular expressions, the (^) symbol matches on the beginning of the target string and the ($) symbol matches on the end of the target string. To demonstrate this, let's store some text:

 Launch code in new window » Download code as text file »

  • <!--- Store some text. --->
  • <cfsavecontent variable="strText">
  • Laughing as he snatched another plate from the stack,
  • Chalked his hands and monstrous back,
  • Said, Boy, stop lying and don't say you've forgotten!
  • Trouble with you is you aint been SQUATTIN!
  • </cfsavecontent>

Now, let's apply a regular expression that matches the entire string (^) to ($):

 Launch code in new window » Download code as text file »

  • <!--- Match the entire string from start to end. --->
  • <cfset strText = strText.ReplaceAll(
  • "(^[\w\W]+$)",
  • "BEGIN::$1::END"
  • ) />

... we get the following output:

BEGIN::
Laughing as he snatched another plate from the stack,
Chalked his hands and monstrous back,
Said, Boy, stop lying and dont say you've forgotten!
Trouble with you is you aint been SQUATTIN!
::END

Notice that the (^) and ($) did indeed match the start and end of the string. Also, notice that we used a simple expressions [\w\W]+ to match every character in the string. Since \w is the word character and \W is the non-word character, we are definitely going to match every single character that we come across (remember your Ven diagrams).

Now, there is a regular expression flag, (?m), that tells the regular expression to match (^) at the beginning of EVERY line and to match ($) at the end of EVERY line. Let's run the same expression above except this time we will run a multiline flag on it.

 Launch code in new window » Download code as text file »

  • <!--- Match the multiline string from start to end. --->
  • <cfset strText = strText.ReplaceAll(
  • "(?m)(^[\w\W]+$)",
  • "BEGIN::$1::END"
  • ) />

Notice that we start the expression with the (?m) multiline flag. Running this we get the following output:

BEGIN::
Laughing as he snatched another plate from the stack,
Chalked his hands and monstrous back,
Said, Boy, stop lying and dont say you've forgotten!
Trouble with you is you aint been SQUATTIN!
::END

But wait, isn't that the same exact thing as before? Yes. The problem with our example is that regular expressions are GREEDY. Our regular expression is trying to match as much as possible while still allowing matches on every line. To fix this, we must modify the expression to be non-greedy. To do so, we will add the (?) character after the (+) character:

 Launch code in new window » Download code as text file »

  • <!---
  • Match the multiline string from start to end. Run
  • this expression as a non-greedy search.
  • --->
  • <cfset strText = strText.ReplaceAll(
  • "(?m)(^[\w\W]+?$)",
  • "BEGIN::$1::END"
  • ) />

This gives us the desired output:

BEGIN::
Laughing as he snatched another plate from the stack,::END
BEGIN::Chalked his hands and monstrous back,::END
BEGIN::Said, Boy, stop lying and don't say you've forgotten!::END
BEGIN::Trouble with you is you aint been SQUATTIN! ::END

Notice that the BEGIN and END strings are inserted at the beginning and the end of every line respectively.

Ok, so that might not look too sexy, but it is very useful. One of the places that I love to use something like this is when I am scripting database calls. Image that I had a delimited list of data in a data file like (we will simulate this in a CFSaveContent tag):

 Launch code in new window » Download code as text file »

  • <!--- Simulate a delimited data file via CFSaveContent. ---->
  • <cfsavecontent variable="strText">
  • 1,Libby,9.0
  • 2,Anna,7.5
  • 3,Donna,6
  • 4,Sarah,9.5
  • </cfsavecontent>

We can run a multiline regular expression on this that will allow us to create a SQL statement for every line:

 Launch code in new window » Download code as text file »

  • <!--- Generate SQL scripts. --->
  • <cfset strSQL = strText.ReplaceAll (
  • "(?m)^(\s)*([0-9]+),([^ ]+),([0-9.]+)$",
  • "UPDATE girl SET hotness = $4 WHERE id = $2;"
  • ) />

Here, we are using the (?m) multiline flag. We are also grouping the different data fields. This will give us the output:

UPDATE girl SET hotness = 9.0 WHERE id = 1;
UPDATE girl SET hotness = 7.5 WHERE id = 2;
UPDATE girl SET hotness = 6 WHERE id = 3;
UPDATE girl SET hotness = 9.5 WHERE id = 4;

Dump that in SQL Analyser or a CFQuery tag and we are good to go. Pretty cool huh?

If you are not using regular expressions, learn them. They are really awesome and so freakin' powerful. The multiline flag doesn't come alll that often, but it is great anytime to you want to treat each line as an individual entity. For more control, you can use this with the Java Pattern / Matcher to handle each line on it's own.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Feb 2, 2007 at 11:09 PM // reply »
165 Comments

Note that anytime, even when using multi-line mode, you should be able to use \A to match the start of the string and \z to match the end. Also note that I haven't tested those operators in ColdFusion, so here's hoping it's not another feature ColdFusion left off the regex support list.


Feb 3, 2007 at 7:53 PM // reply »
7,572 Comments

Just so we're on the same page, is the \A and \z stuff equivalent to ^ and $ when multi-line matching is NOT enabled? And, if I understand what you are saying, then even if you are doing multi-line matching, \A and \z will still match the very beginning / end of the ENTIRE string.

If that is the case, awesome. I was wondering what the heck those were for. I should just learn by now that none of this stuff is excess, that if I don't see the difference between two things, I probably am not understanding it.


Feb 3, 2007 at 9:52 PM // reply »
165 Comments

[If that is the case, awesome.]

That is the case, and it is indeed quite nifty. Another related (but not nearly as useful, IMO) operator is \Z (uppercase z), which matches at the end of the string and never before line breaks, except for the very last line break if the string ends with a line break. (Whoever thought up that operator had too much free time.)


Jan 10, 2008 at 7:01 PM // reply »
165 Comments

Hi again, Ben. I've recently written up a post on the nitty-gritty of the the regex singleline and multiline flags (and why the names can be highly misleading) at http://blog.stevenlevithan.com/archives/singleline-multiline-confusing . Just referencing it here for other people who find this, since I assume you're fairly familiar with how these modes work.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »
Mar 21, 2010 at 3:42 AM
A New Wrist Pain
Chiropractic treatment is one of the best methods for treating numerous health problems naturally. After years of experience being a chiropractor, I have found that it is a powerful way to solve many ... read »
Mar 20, 2010 at 12:07 PM
Drawing On The iPhone Canvas With jQuery And ColdFusion
Simply awesome. Saved my day. ... read »
Mar 20, 2010 at 9:00 AM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
I would like to say thx for an easy way to create a bottom bar. I do have a ?. Is it possible to center the bar if i want to resize it to ex 85%. Regards Offenbach ... read »
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »
Jim
Mar 19, 2010 at 4:49 PM
Nobody Puts Baby In The Corner!
Wow. This is like suddenly finding a support group for your secret shame. I'm not alone! I always liked this movie, even though it is extremely cheesy. I just wish Jennifer Grey hadn't gotten the ... read »