Using .NET (dotnet) Regular Expressions In ColdFusion

Posted May 21, 2010 at 9:21 AM by Ben Nadel

Tags: ColdFusion

Since I am heading off to Scotch On The Rocks tomorrow, I figured this will pretty much be my last post for the next week or so. And, since Regular Expression Day 2010 ends in about a week, I thought I would try something that I have never tried before: loading and running a .NET (dotnet) regular expression inside of ColdFusion. Starting with ColdFusion 8, Adobe has added a .NET Integration Service to the ColdFusion installer that allows your ColdFusion code to access local and remote .NET (dotnet) assemblies (DLL files). Somewhat like its Java integration, ColdFusion does this by creating proxies to the actual .NET classes.

NOTE: As this is the first time I have played with .NET integration, please take any technical explanation with a grain of salt as it is likely flawed.

In ColdFusion, we have access to the POSIX regular expression engine and the underlying Java regular expression engine; so, why even bother using the .NET (dotnet) regular expression engine? For the most part, RegEx engines are the same; but, each flavor has its own specialized features. DotNet is no different. Unfortunately, I don't know anything about the .NET regular expression engine since I've never used it before. As such, I am going to flagrantly borrow from the flagrant badassery of RegEx guru, Steven Levithan.

In .NET regular expressions, you can use named collections to help keep track of patterns matched within a given string. Using a special notation, you can either push elements onto a named collection, pop elements off of a named collection, or check to see if the collection contains any remaining elements. I won't go into too much detail on how this works (as I just tried this myself for the first time), I'll just defer to Steve Levithan's blog post on this matter.

That said, let's use this depth-tracking regular expression construct inside ColdFusion using the .NET (dotnet) integration services. In .NET, the regular expression class, System.Text.RegularExpressions.Regex, is compiled within the System.dll assembly, which is, itself, contained within the root of the .NET framework (probably buried somewhere in your Windows folder - I had to search for mine). In the following demo, we're going to match patterns in which a string of "A" characters is followed by an equal number of "B" characters.

  • <!--- Store the path to the .NET framework. --->
  • <cfset frameworkDirectory = "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\" />
  •  
  • <!---
  • Create an instance of the .NET RegEx CLASS definition. When
  • ColdFusion creates a .NET class, it works as if you are working
  • with a Java class - it gives you the static class until you call
  • the constrcutor or call a non-static method (at which point it
  • calls the default constructor if possible).
  • --->
  • <cfobject
  • name="pattern"
  • type="dotnet"
  • class="System.Text.RegularExpressions.Regex"
  • assembly="#frameworkDirectory#System.dll"
  • />
  •  
  •  
  • <!---
  • Create a .NET regular expression pattern. This uses
  • .NET's unique "depth" mechanism to track matching and
  • counter-matching patterns.
  •  
  • NOTE: I don't really know anything about this - I am borrowing
  • it from Steve Levithan:
  •  
  • http://blog.stevenlevithan.com/archives/balancing-groups
  • --->
  • <cfsavecontent variable="dotNetPattern">(?x)
  •  
  • ^
  •  
  • <!---
  • For each A that we encounter, push it onto the a stack with
  • the name "Counter".
  • --->
  • (?<Counter>A)+
  •  
  • <!---
  • For each B that we encounter, pop one item off of the stack
  • with the name "Counter."
  • --->
  • (?<-Counter>B)+
  •  
  • <!---
  • Once we have finished matching our A/B string, check to see
  • if there are any items remaining on the "Counter" stack. If
  • there are, apply an empty negative look-ahead (that will
  • always fail).
  • --->
  • (?(Counter)(?!))
  •  
  • $
  •  
  • </cfsavecontent>
  •  
  • <!---
  • Now that we have our .NET regular expression pattern, let's
  • instantiate and initialize our pattern object. Remember, the
  • init() method is how we call the constructor (same as with
  • the Java classes).
  • --->
  • <cfset pattern.init( dotNetPattern ) />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Now, let's check to see if variaous strings match against this
  • regular expression pattern.
  •  
  • NOTE: Only the fourth one *should* match.
  • --->
  • <cfoutput>
  •  
  • #pattern.isMatch( "AAA" )#<br />
  • #pattern.isMatch( "AAAB" )#<br />
  • #pattern.isMatch( "AAABB" )#<br />
  •  
  • <!--- Three and three. --->
  • #pattern.isMatch( "AAABBB" )#<br />
  •  
  • #pattern.isMatch( "AAABBBB" )#<br />
  • #pattern.isMatch( "AAABBBBB" )#<br />
  •  
  • </cfoutput>

Here, I am using the "?<Counter>", "?<-Counter>", and "?(Counter)" constructs to push, pop, and check the "Counter" stack respectively. Every time I hit an "A", I push and everytime I hit a "B", I pop. Then, at the end of the string, I make sure that the collection is empty (indicating an even number of push and pop actions).

When I run the above code, I get the following output:

NO
NO
NO
YES
NO
NO

As you can see, only the fourth string, "AAABBB," was a match for our .NET regular expression pattern. This is because the string was composed of three "A"s followed by an equal number of three "B"s.

In other regular expression engines, you can easily match three "A"s followed by three "B"s. What makes the .NET (dotnet) regular expression engine so exciting is that equal matching (3 and 3) doesn't have to have a predetermined length! I wonder what other kinds of gems are available in the .NET pattern classes? Special thanks to Steven Levithan for providing the actual RegEx understanding.



Reader Comments

May 21, 2010 at 10:41 AM // reply »
1 Comments

Thanks Ben for the wonderful tutorial.

But..I'm getting the following error!!

If a dll is specified in the assembly list, DotNetExtension must also be installed.

Any idea?


May 21, 2010 at 10:55 AM // reply »
11,238 Comments

@Kevin,

The .NET Integration stuff is actually an additional service that needs to be installed that runs along side the ColdFusion Application service. This way, you can turn it on and off without stopping ColdFusion.

It's one of the checkboxes in the ColdFusion installer. I never install it so last night when I wanted to play around with it, I actually ended up just uninstalling and re-installing ColdFusion (I couldn't figure out how to run an "update" for the installer without kicking into multi-instance mode).

I'm sure there is a way to just add on the .NET Integration stuff, but that goes beyond my understanding.


May 21, 2010 at 11:41 AM // reply »
3 Comments

No need to reinstall CF to get the .net integration services. On the CD or in the extras download is a CF8-DotNetIntegration.exe/ColdFusion_9_DotNetIntegration_WWE.exe to install the .net integration service into a existing installation.


May 21, 2010 at 11:45 AM // reply »
11,238 Comments

@Reto,

What happens if you got the installer from the website, so it's a single EXE file? Is the DotNet installer just put in the ColdFusion install directories?


May 21, 2010 at 12:02 PM // reply »
3 Comments

If you don't install the service with the ColdFusion installer you will not have the .net integration installer on your disk. You will need to take it from the cd or download. For CF8 download it was in a big extras.zip file, but the installer is just a single exe file. The cf8 download was just possible after a login with a purchased license on adobe.com. Don't know about CF9.

It's an Install Anywhere installer like for CF itself and looks the same. You can choose some options like path and installation mode:

Standalone;
You can install the .net integration services on a windows server where no ColdFusion is installed and connect from unix cf installation to use the .net feature.

with ColdFusion:
CF will be configured to use the new .net integration services installation.


May 21, 2010 at 12:06 PM // reply »
11,238 Comments

@Reto,

Hmm, I'll have to check out the extras.zip file on my home machine (at work, I am running in multi-instance mode, which I am still learning about).


Jun 4, 2010 at 8:31 PM // reply »
13 Comments

For anyone who is interested.

You can also just download the .NET integration services .exe from the adobe website.

http://www.adobe.com/support/coldfusion/downloads.html


Jun 7, 2010 at 9:46 AM // reply »
11,238 Comments

@Kevin,

Awesome!! Thanks for pointing this out. I know people have mentioned that it can be installed separately, but I had no idea where from. This is brilliant, thanks.


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 21, 2013 at 11:51 AM
Ask Ben: Parsing Very Large XML Documents In ColdFusion
Looking at my first ever XML document that I have to parse and put into MS SQL 2000 with CF8. I get it to list the desired Field name, many times over, and have a long list of this field name displa ... read »
May 21, 2013 at 9:25 AM
Turning Off and On Identity Column in SQL Server
you are awesome..i am lucky to get this blog between such a garbage one....Thanks, Prashant ... read »
May 20, 2013 at 4:38 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, Your confusion is well founded, since this is a very confusing features. In fact, it ONLY works if you use array notation. Meaning, that this: arrayToList( query[ "columnName" ] ) ... read »
May 20, 2013 at 4:34 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I was thinking chicken and the egg, I wouldn't have expected it to work in the valuelist going in I guess. Maybe I just need a beer, long day :) ... read »
May 20, 2013 at 4:29 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Dana, That's if you're trying to reference a specific row. In this case, we're trying to reference the entire query column as one cohesive value. So, you are correct that if you wanted to output a ... read »
May 20, 2013 at 4:24 PM
Using A Dynamic Column Name With ValueList() In ColdFusion
I thought when you used array notation to reference queries you always had to have the row or it would throw a similar error as well? ... read »
May 20, 2013 at 11:45 AM
Using jQuery's Animate() Step Callback Function To Create Custom Animations
This is really useful. I found out that you don't actually have to use a dummy css property (surprisingly). To animate a property in a linear-gradient for instance I did this this.css('someLinearGra ... read »
May 20, 2013 at 10:51 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Josh, Oh snap! You're totally right! I'm not sure I've ever tried that. I did know that you can call a number of other array-methods on ColdFusion query columns: http://www.bennadel.com/blog/167 ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools