RegEx API

Compiled regular expressions with PCRE2 syntax: named groups, lookarounds, match objects, and substitution.

Overview

The global identifier RegEx is a constructor namespace. Calling one of its constructors returns a regex instance whose methods are invoked as r.method(...). Successful searches yield RegExMatch instances with their own method set.

Conventions

Construction

RegEx.create(pattern)

Compiles pattern and returns a new regex instance. Returns null if the pattern fails to compile. This is the common entry point.

Returns: A compiled regex instance, or null on a compile failure.

defensive compilation
var r = RegEx.create("([")
if (r == null) {
    print("invalid pattern")
}
RegEx.empty()

Returns an uncompiled regex instance; call r.compile(pattern) before use. Provided for the rare case where you want to build an uncompiled instance and decide the pattern later. Otherwise, prefer RegEx.create.

Compilation & State

r.isValid()

Returns true when a pattern has been successfully compiled, false otherwise.

r.pattern()

Returns the most recently supplied source pattern, or "" for an instance that has never been compiled. clear() invalidates the compiled state but does not zero this string.

r.compile(pattern)

Compiles pattern, replacing any previous pattern. Returns true on success, false on a syntax error.

r.clear()

Drops the compiled pattern so the instance becomes invalid. After this call isValid() is false; pattern() still reports the last source string that was supplied. Returns null.

state lifecycle
var r = RegEx.empty()
print(r.isValid())        // false
print(r.compile("\\d+"))  // true
print(r.pattern())        // "\\d+"
r.clear()
print(r.isValid())        // false
print(r.pattern())        // still "\\d+"

Group Metadata

r.groupCount()

Returns the number of capturing groups in the pattern, excluding group 0. Returns 0 for an uncompiled instance.

r.names()

Returns a list of the named-capture identifiers declared in the pattern, in the order they appear. Unnamed groups are not represented; use groupCount() for the total number of capturing groups.

var r = RegEx.create("(?<year>\\d{4})-(\\d{2})")
print(r.groupCount())   // 2
print(r.names())        // list with one entry: "year"

Matching

Searches subject for the first match. Returns a RegExMatch instance, or null if nothing matches.

r.searchAll(subject, offset?, end?)

Returns every non-overlapping match in subject as a list of RegExMatch instances. Returns an empty list when nothing matches.

r.sub(subject, replacement, all?, offset?, end?)

Substitutes matches in subject with replacement and returns the resulting string. The replacement string supports back-references (\\1, \\g<name>).

substitute
var r = RegEx.create("\\d+")
print(r.sub("hello 42 world 7", "X", false))  // "hello X world 7"
print(r.sub("hello 42 world 7", "X", true))   // "hello X world X"
Note: Calling search, searchAll, or sub on an uncompiled or invalid pattern raises a runtime error ending in pattern is not compiled.

RegExMatch

Returned by r.search and r.searchAll. Methods are invoked as m.method(...).

m.subject()

Returns the original subject the match was produced from.

m.groupCount()

Returns the number of capturing groups, excluding group 0.

m.names()

Returns a map of named-group identifier to group index.

m.strings()

Returns all matched substrings as a list, with the whole match at index 0 followed by each capturing group. Unmatched groups are empty strings.

m.string(name)

Returns the substring for the given group.

m.start(name)

Returns the byte offset where the group starts.

m.end(name)

Returns the byte offset just past the end of the group.

Examples

Find a Single Match

var r = RegEx.create("(?<word>\\w+)\\s+(\\d+)")
var m = r.search("hello 42 world 7")
print(m.string(0))        // "hello 42"
print(m.string("word"))   // "hello"
print(m.string(2))        // "42"
print(m.start(0))         // 0
print(m.end(0))           // 8

Iterate Every Match

var r = RegEx.create("\\d+")
var hits = r.searchAll("hello 42 world 7")
for (var i = 0; i < length(hits); i = i + 1) {
    print(hits[i].string(0))   // "42", then "7"
}

Extract Named Groups

var r = RegEx.create("(?<key>\\w+)=(?<value>\\w+)")
var m = r.search("mode=fast")
print(m.strings())          // list: "mode=fast", "mode", "fast"
print(m.names())            // map: "key" -> 1, "value" -> 2
print(m.string("value"))    // "fast"