views:

204

answers:

3

Hi,

I'm using ColdFusion's reReplace() function for regular expression pattern replacement.

I'd like to use a function call for the replacement string, and pass a matched backreference to it.

Something like this:

<cfset s = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" />
<cfset s = reReplace(s, "STARTDATE_([\s-.:0-9]*)_ENDDATE", dateAdd("h", 1, "\1")) />

But that fails because "The value of parameter 3, which is currently \1, must be a class java.util.Date value."

Is there any other way to achieve this?

Thanks, Stu

A: 

As far as I can see from your code example, you want to replace the whole string with a date one hour later than shown in your string. Since there are troubles with the reReplace I would try to strip off the non-date part of the string using the replace() or replaceNoCase() functions.

<cfset s = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" />
<cfset s = replaceNoCase(replaceNoCase(s, "STARTDATE_", ""),"_ENDDATE","")>
<cfoutput>
    <cfif isDate(s)>
        before: #s# after: #dateAdd("h", 1, s)#
    </cfif> 
</cfoutput>

dateAdd() requires a valid date as parameter, I don't think you can do this with a regex backreference which will allways be a string.

Andreas Schuldhaus
Hi Andreas - thanks for the reply. The example was super-simplified to explain my problem. What I really need to do is replace multiple occurrences of dates inline within a large text document. So just extracting the date doesn't work for me. And repeated calls to reFind with returnsubexpressions=true, then calling replace on each match is too slow... Thanks anyway!
stubotnik
+2  A: 

Hi Stu,

I'm not too sure if what you're wanting to do is possible by the approach described in your example, but here is an outline of another approach that should work.

  1. Strip out the date string
  2. Convert this sting to a time object using CreateDateTime
  3. Perform any date operations on this object ie DateAdd
  4. Convert back to a string using DateFormat
  5. Do the replace

When using the built-in ColdFusion date and time functions I like to always make sure I'm passing in a date/time object rather that a date/time string for parameters that require a date/time object. This is because ColdFusion may interpret the strings days as months or vice versa.

Gary Boyle
You probably want parseDate() instead of createDateTime(), but otherwise on the money.
Ben Doom
Hi Gary - I was hoping to avoid going down this road for performance reasons (see comment on Andreas' answer) but it looks like I've no alternative. Accepting this as the answer - cheers
stubotnik
A: 

I have a utility that allows you to achieve what you want.

Syntax isn't quite a same, and a tad irritating for 'simple' things, but ultimately it is more flexible.

Basically you write a function which accepts a Match string and Groups array and returns a String - inside the function you can do what you like and it'll get applied to each match.

Like so:

<cfset Jrex = createObject('component','jre-utils').init() />


<cfset MyString = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" />
<cfset MyRegex = "STARTDATE_([\s-.:0-9]*)_ENDDATE" />
<cfset MyString = Jrex.replace( MyString , MyRegex , addHour , 'all' )/>


<cffunction name="addHour" returntype="String" output="false">
    <cfargument name="Match"  type="String"/>
    <cfargument name="Groups" type="Array" default="#ArrayNew(1)#"/>

    <cfset var Result = DateAdd('h',1,Groups[1]) />

    <cfreturn DateFormat( Result , 'yyyy-mm-dd' )
        & ' ' & TimeFormat( Result , 'HH:mm:ss' )
        />
</cffunction>


Details and download here: http://www.hybridchill.com/projects/jre-utils.html

One thing to bear in mind is that this uses the java.util.regex engine, which is different to CF's org.apache.oro.text.regex engine, and whilst this provides more features, a few things don't work (yet).

The next version is going to be a fairly major release, so any feedback you might have is very much welcome.

Specifically, one functionality I've been pondering is how to avoid the long-winded manual function callback method as above - perhaps enabling something like this:

Jrex.replace( MyString , MyRegex , "\F:DateAdd('h',1,\1)" , 'all' )

Would be good to hear if anyone has thoughts on that.

Peter Boughton
Hi Peter - the example failed for me with "The appendReplacement method was not found". But otherwise this looks exactly like what I was hoping for. Thanks!
stubotnik
Hi stubotnik, that's a bit odd, the appendReplacement method is part of Java and has existed since 1.4 (and I don't since CF runs against earlier than 1.4) - can you confirm what CF and Java versions you're running with?
Peter Boughton
CF 9 and Java 1.6.0_14. "method not found" is thrown when CF has problems casting variables and figuring out the correct overloaded method to use. Maybe that's the issue?
stubotnik
Peter Boughton