Regular expressions
Synopsis
$regcomp(pattern)
$regcomp_cs(pattern)
$regexec(compiled-pattern text)
$regmatches(compiled-pattern count text)
$regerror(compiled-pattern)
$regfree(compiled-pattern)
These C built-in functions compile and execute regular expressions. They are separate from EPIC's wildcard patterns. Their syntax is supplied by the regex library selected at build time: the PCRE2 POSIX interface when configured, otherwise the platform's POSIX regex interface. Compilation requests extended syntax, plus the platform's enhanced flag when available; do not assume every build accepts the same extensions.
Compiling and matching
Regcomp compiles a case-insensitive pattern; regcomp_cs omits the case-insensitive flag. Each returns an opaque string suitable for storing in a script variable and passing unchanged to the other functions. The string encodes a library structure with process-local resources; it is not a portable serialized regex, ordinary lvalue name, or pattern that can be saved and restored in a later client session.
Compilation can fail even though a nonempty opaque string is returned. Check regerror immediately after compilation, before attempting to use the handle for matching. Do not pass unsuccessfully compiled or invented handles to the execution functions.
Regexec applies a successfully compiled expression to the supplied text. It returns the regex library's numeric status: 0 means a match; nonzero means no match or another library error. It is therefore incorrect to use a true result as “matched,” or to assume every nonzero result is exactly 1.
Regular expressions can match a substring unless the pattern explicitly anchors its beginning and end. For example, abc can match inside abc def; use ^abc$ when the whole text must be exactly that value, subject to the selected regex syntax and flags.
Errors are shared state
regerror(handle) returns a human-readable error string, or empty when the shared status is zero. The status records the most recent regcomp, regcomp_cs, regexec, or successful entry into regmatches library execution; it is not stored independently with each handle. An operation on another expression can overwrite the status before you inspect it.
A no-match status can also have an explanatory string, so a nonempty error description does not by itself distinguish invalid syntax from ordinary nonmatching input. Check the operation's result in context. regfree does not reset this shared status.
Substring matches
Regmatches returns start/length pairs for up to count match slots. Slot zero describes the whole match; subsequent slots describe parenthesized subexpressions. Positions are converted from library byte offsets to Unicode code-point offsets, suitable for mid, rather than returned as raw UTF-8 byte offsets. Output stops at the first unmatched slot; it is not guaranteed to contain every requested slot.
A nonmatch returns empty and updates the shared regex status. For a successfully compiled abc (def) expression, $regmatches($compiled 2 abc def) returns 0 7 4 3: the whole match followed by the def capture.
Resource lifetime and input validation
Compiled expressions allocate library resources. Release a successfully compiled expression with regfree when it is no longer needed. Copies of an opaque string share the underlying resources; copying the text does not clone the compiled expression. After cleanup, using any copy or freeing it again is invalid and can crash the client. Clearing a script variable alone does not free the regex library's allocation.
regexec, regmatches, regerror, and regfree initialize their destination structure and require Base85 decoding to produce exactly one regex_t. Failed decoding or a wrong decoded size prints First argument to $<function>() is not a value from $regcomp() and returns empty without changing the shared regex status. regfree also returns empty after successful cleanup.
The decoding and size checks do not verify ownership, pointer validity, or successful compilation. Use only an unchanged result from the current process, and preserve its lifetime across all matching operations.
Example
The following demonstrates compilation and matching, with immediate error inspection:
@ original = [abc def];
@ compiled = regcomp(abc);
if (regerror($compiled) != []) {
xecho -b Compile error: $regerror($compiled);
} else {
@ result = regexec($compiled $original);
if (result == 0) {
xecho -b It matched!;
} else {
xecho -b Regex status $result: $regerror($compiled);
};
@ regfree($compiled);
};
On successful compilation and execution it prints It matched!, then releases the compiled expression. The stored string must not be used afterward.
Practical limits
Compile once and reuse a valid handle rather than recompiling for every event. The library, pattern, and input determine matching cost; regular expressions are not universally faster than wildcard matching. Keep text and patterns within the applicable library and client limits, and read the individual function pages for missing-input behavior and capture-count restrictions.
No IRC connection or script package is required. The regex backend is a build/platform dependency, and callback code using these functions still follows normal expansion and expression rules.
Source references
source/functions.c: compilation flags, Base85 structures, sharedlast_regex_error, execution, capture conversion, and cleanup checks.include/irc_std.handconfigure.ac: PCRE2 POSIX versus platform regex selection.source/ircaux.c: Base85 transform implementation.include/functions.h: function-argument parsing and return conversion.