Runtime verified Test scripts included

Syntax

RegExMatch(sourceString, regExPattern, returnValue[, regExOptions, ...])  →  string

Parameters

Name Type Required Description
sourceString string | number Yes String to match against
regExPattern string Yes Regular expression to apply
returnValue string | number Yes Index or name of the capture group to return; 0 returns the whole match
regExOptions string No A .NET RegexOptions member name such as IgnoreCase or Multiline
regExOptionsN string No Any number of further RegexOptions member names

There is no upper bound on the number of option names.

Example

%%[
  VAR @digits
  SET @digits = RegExMatch("order-4821-eu", "[0-9]+", 0)
]%%
Number: %%=v(@digits)=%%

Renders Number: 4821.

A capture group is the usual way to pull one part out of a structured value:

%%[
  VAR @region
  SET @region = RegExMatch("order-4821-eu", "order-([0-9]+)-([a-z]+)", 2)
]%%
Region: %%=v(@region)=%%

That renders Region: eu.

A pattern that matches nothing looks exactly like a pattern that matched but selected a group that does not exist — see below before treating an empty result as a failed match.

Return value

string — the text of the selected capture group.

The empty string is the only sentinel value, and it is returned for three different reasons: the pattern found nothing, the requested capture group does not exist, or the source was empty. Matched text is otherwise an open domain, so there is no closed set of values to test for.

Behaviour

A group selector of 0 returns the whole match, and a higher index returns that capture group. Against order-4821-eu, the pattern [0-9]+ with selector 0 gives 4821, while order-([0-9]+)-([a-z]+) gives 4821 for selector 1 and eu for selector 2.

The selector may be a number, the same number as a string, or a named capture group. Passing "0" in quotes gives 4821 just as the bare 0 does, and a pattern declaring a named group returns 4821 when the group’s name is passed as the selector.

Only the first match is returned. The pattern [a-z][0-9] against a1 b2 c3 gives a1; there is no way to reach the later matches from a single call.

Numbers are accepted as the source. Matching [0-9]+ against the numeric literal 4821 gives 4821, so a numeric field needs no conversion first.

Matching is case-sensitive, unlike the other String functions

Call Renders
RegExMatch("ORDER-4821", "order", 0) (empty)
RegExMatch("ORDER-4821", "order", 0, "IgnoreCase") ORDER
RegExMatch("ORDER-4821", "order", 0, "ignorecase") ORDER

IndexOf, Replace and ReplaceList all ignore case, so a search value moved from one of them into a regular expression silently stops matching. Append the IgnoreCase option, or write the pattern to accept both casings. The option name itself is not case-sensitive — the all-lowercase spelling works the same way.

More than one option may be passed: two option names and five option names were both accepted on a single call, which is why the argument count has no upper bound.

An empty result does not mean the pattern failed

Call Renders Why
RegExMatch("order-4821-eu", "[0-9][0-9][0-9][0-9][0-9][0-9]", 0) (empty) no match
RegExMatch("order-4821-eu", "order-([0-9]+)-", 5) (empty) index past the last group
RegExMatch("order-4821-eu", "[0-9]+", 1) (empty) the pattern declares no group
RegExMatch("order-4821-eu", "order-([0-9]+)-", "nope") (empty) no group of that name
RegExMatch("", "[0-9]+", 0) (empty) empty source

All five return the same value at HTTP 200, so a caller cannot tell a mis-typed group selector from a genuine non-match by the result alone. Two inputs behave differently and abort the page instead: a malformed pattern such as an unclosed group, and an option name that is not a real RegexOptions member. Both discard everything the page had already rendered, so keep them out of production paths rather than relying on an empty return.

Catalogued on Differs from official docs. The docs are silent on the casing and on the option count rather than wrong about them, so the entry is not flagged as contradicting them.

Show test script
%%[
  VAR @b
  SET @b = RequestParameter("b")

  /* group selection, casing, edge shapes and the accepted argument types */
  IF @b == "safe" THEN
    OutputLine(Concat("G0=[", RegExMatch("order-4821-eu", "[0-9]+", 0), "]"))
    OutputLine(Concat("G1=[", RegExMatch("order-4821-eu", "order-([0-9]+)-", 1), "]"))
    OutputLine(Concat("G2=[", RegExMatch("order-4821-eu", "order-([0-9]+)-([a-z]+)", 2), "]"))
    OutputLine(Concat("GSTR0=[", RegExMatch("order-4821-eu", "[0-9]+", "0"), "]"))
    OutputLine(Concat("NAMED=[", RegExMatch("order-4821-eu", "order-(?<num>[0-9]+)-", "num"), "]"))
    OutputLine(Concat("NOMATCH=[", RegExMatch("order-4821-eu", "[0-9][0-9][0-9][0-9][0-9][0-9]", 0), "]"))
    OutputLine(Concat("CASEDEF=[", RegExMatch("ORDER-4821", "order", 0), "]"))
    OutputLine(Concat("CASEOPT=[", RegExMatch("ORDER-4821", "order", 0, "IgnoreCase"), "]"))
    OutputLine(Concat("OPTLOWER=[", RegExMatch("ORDER-4821", "order", 0, "ignorecase"), "]"))
    OutputLine(Concat("NUMSRC=[", RegExMatch(4821, "[0-9]+", 0), "]"))
    OutputLine(Concat("EMPTYSRC=[", RegExMatch("", "[0-9]+", 0), "]"))
    OutputLine(Concat("FIRSTONLY=[", RegExMatch("a1 b2 c3", "[a-z][0-9]", 0), "]"))
    OutputLine(Concat("GROUPMISS=[", RegExMatch("order-4821-eu", "[0-9]+", 1), "]"))
    OutputLine(Concat("BADGROUP=[", RegExMatch("order-4821-eu", "order-([0-9]+)-", 5), "]"))
    OutputLine(Concat("BADNAME=[", RegExMatch("order-4821-eu", "order-([0-9]+)-", "nope"), "]"))
    OutputLine(Concat("TWOOPTS=[", RegExMatch("ORDER-4821", "order.4821", 0, "IgnoreCase", "Singleline"), "]"))
  ENDIF

  /* the option list has no upper bound */
  IF @b == "manyopts" THEN
    OutputLine(Concat("--- manyopts start ---"))
    OutputLine(Concat("MANYOPTS=[", RegExMatch("ORDER-4821", "order.4821", 0, "IgnoreCase", "Singleline", "Multiline", "ExplicitCapture", "IgnorePatternWhitespace"), "]"))
    OutputLine(Concat("--- manyopts done ---"))
  ENDIF

  /* every branch below aborts the page: the start marker never renders */
  IF @b == "badregex" THEN
    OutputLine(Concat("--- badregex start ---"))
    OutputLine(Concat("BADREGEX=[", RegExMatch("order-4821-eu", "order-([0-9]+", 0), "]"))
  ENDIF

  IF @b == "badopt" THEN
    OutputLine(Concat("--- badopt start ---"))
    OutputLine(Concat("BADOPT=[", RegExMatch("order-4821-eu", "[0-9]+", 0, "NotARealOption"), "]"))
  ENDIF

  IF @b == "a2" THEN
    OutputLine(Concat("--- a2 start ---"))
    OutputLine(Concat("A2=[", RegExMatch("order-4821-eu", "[0-9]+"), "]"))
  ENDIF
]%%

Availability

Platform Available
Marketing Cloud Engagement Yes
Marketing Cloud Next No

See also