user964202
user964202

Reputation: 73

Parsing variables within a string using a Regular Expression

I've got a bit of a problem with regular expressions with ColdFusion.

I have a string:

Hi my name is {firstname}. and i live in {towncity} my email address is {email}

What I would like to know is how would I go about finding all strings, within my string, that are encased within a set of {} brackets? I would like to split all the matching strings into an array so I can use the results of query data.

Also is this a commonly used pattern for processing strings within matching strings for merging variable data ?

Any help greatly appreciated.

Upvotes: 1

Views: 2108

Answers (3)

Peter Boughton
Peter Boughton

Reputation: 112170

Simple Answer

To find all the brace-encased strings, you can use rematch and the simple expression \{[^{}]+\}

Explanation

The backslashes \ before each brace are to escape them, and have them act as literal braces (they carry special meaning otherwise).

The [^...] is a negative character class, saying match any single char that is NOT one of those contained within, and the greedy + quantifier tells it to match as many as possible, but at least one, from the preceding item.

Thus using [^{}]+ between the braces means it will not match nested or unmatched braces. (Whilst using \{.*?\} could match two opening braces. Note: the *? is a lazy quantifier, it matches nothing (if possible), but as many as required.)

Extended Answer

However, since you say that the results come from a query, a way to only match the values you're dealing with is to use the query's ColumnList to form an expression:

`\{(#ListChangeDelims(QueryName.ColumnList,'|')#)\}`

This changes ColumnList into a pipe-delimited list - a set of alternatives, grouped by the parentheses - i.e. the generated pattern will be like:

 \{(first_name|towncity|email)\}

(with the contents of that group going into capture group 1).

To actually populate the text (rather than just matching) you could do something similar, except there is no need for a regex here, just a straight replace whilst looping through columns:

<cfloop index="CurColumn" list=#QueryName.ColumnList#>
    <cfset text = replace( text , '{#CurColumn#}' , QueryName[CurColumn][CurrentRow] , 'all' ) />
</cfloop>

(Since this is a standard replace, there's no need to escape the braces with backslashes; they have no special meaning here.)

Upvotes: 5

user2014963
user2014963

Reputation:

Use the reMatch(reg_expression, string_to_search) function.

The details on Regular Expressions in Coldfusion 10 are here. (I believe the regexp in CF8 would be roughly the same.)

Use the following code.

<cfset str = "Hi my name is {firstname}. And I live in {towncity} my email address is {email}.">
<cfoutput>Search string: <b>#str#</b><br />Search result:<br /></cfoutput>
<cfset ret = reMatch("\{[\w\s\(\)\+\.@-]+\}", str)>
<cfdump var ="#ret#">

This returns an array with the following entries.

  • {firstname}
  • {towncity}
  • {email}

The [] brackets in CF regular expressions define a character set to match a single character. You put + after the brackets to match one or more characters from the character set defined inside the []. For example, to match one or more upper case letters you could write [A-Z]+.

As detailed in the link above, CF defines shortcuts to match various characters. The ones I used in the code are: \w to match an alpha-numeric character or an underscore, \s to match a whitespace character (including space, tab, newline, etc.).

To match the following special characters +*?.[^$({|\ you escape them by writing backslash \ before them.

An exception to this is the dash - character, which cannot be escaped with a backslash. So, to use it as a literal simply place it at the very end of the character set, like I did above.

Using the above regular expression you can extract characters from the following string, for example.

<cfset str = "Hi my name is { John Galt}. And I live in {St. Peters-burg } my email address is {john@exam_ple.com}.">

The result would be an array with the following entries.

  • { John Galt}
  • {St. Peters-burg }
  • {john@exam_ple.com}

Upvotes: 1

existdissolve
existdissolve

Reputation: 3114

There may be much better ways to do this, but using something like rematch( '{.*?}', yourstring ) would give you an array of all the matches.

For future reference, I did this with the excellent RegExr, a really nice online regex checker. Full disclosure, it's not specifically for ColdFusion, but it's a great way to test things out.

Upvotes: 0

Related Questions