Harnessing Rexx’s Built‑In REGEXP: A Practical Guide to Pattern Matching
Rexx’s built‑in REGEXP function lets you perform POSIX‑style pattern matching without external libraries. Learn how to extract substrings, pre‑compile patterns for speed, and avoid common pitfalls like backtracking and legacy support gaps.
01 May 2026, 21:02 UTC

Why REGEXP Matters in Rexx
Rexx is often celebrated for its readability and simplicity, but many developers overlook the power packed into its native REGEXP function. Unlike external regex libraries, REGEXP is part of the core language in most modern Rexx implementations (IBM Rexx, OpenRexx, GNU Rexx). It returns the start and end positions of the first match, letting you slice out substrings with SUBSTR without any extra dependencies.
Getting Started: The Basic API
The signature is straightforward:
start = REGEXP(pattern, string, &end, /* optional flags */)
pattern– a POSIX extended regular expression.string– the text to search.&end– an output variable that receives the ending index of the match.flags– optional modifiers such asCOMPfor pre‑compilation.
If no match is found, start is zero and &end is set to zero as well.
Extracting an Email Address
Below is a minimal script that finds the first email address in a string and prints it. The example works on any Rexx interpreter that supports the REGEXP API.
string = "Please contact us at support@example.com for assistance."
/* Simple email regex – not RFC‑compliant, but good for demo */
pattern = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
start = REGEXP(pattern, string, end)
if start > 0 then
say "Found: " + SUBSTR(string, start, end - start + 1)
else
say "No email found."
Running this on OpenRexx or IBM Rexx will produce:
Found: support@example.com
Because the function returns indices, you can reuse the same pattern to extract multiple substrings by looping over REGEXP with an offset. For example, to capture every email in a block of text, you can increment the search start position after each match.
Pre‑compiling for Performance
When the same pattern is used repeatedly – say, inside a tight loop – the interpreter can pre‑compile the regex once and reuse the compiled object. Pass the COMP flag to REGEXP and store the returned compiled handle:
compiled = REGEXP(pattern, /* string */, /* end */, COMP)
/* Now use the compiled handle */
start = REGEXP(compiled, string, end)
Measure the difference with TIMER:
time1 = TIMER()
repeat 1000
start = REGEXP(pattern, string, end)
endtime1 = TIMER()
time2 = TIMER()
repeat 1000
start = REGEXP(compiled, string, end)
endtime2 = TIMER()
echo "Uncompiled: " + (endtime1 - time1)
echo "Compiled: " + (endtime2 - time2)
On a typical machine, the compiled version is noticeably faster, especially for large strings or complex patterns.
Limitations and Pitfalls
- Legacy Environments: Some early IBM Rexx for z/OS releases lack
REGEXP. In those cases you must fall back to manual string functions or external utilities. - Backtracking Hazards: Greedy quantifiers like
.*can cause catastrophic backtracking on malformed input. Keep patterns as tight as possible and test against worst‑case strings. - Unicode Support: Most Rexx regex engines treat the string as a byte array. If you need true Unicode code‑point awareness, consider normalizing the string first or using a third‑party library.
- Injection Risk: If a pattern originates from user input, validate or escape it before passing to
REGEXPto avoid accidental logic changes or denial‑of‑service.
When to Use REGEXP vs. Manual Parsing
Use REGEXP when:
- The pattern is complex (alternation, groups, character classes).
- You need to extract or validate data in a single pass.
- Portability across Rexx implementations is required.
Opt for manual parsing when:
- The pattern is simple (e.g., fixed delimiters).
- Performance is critical and you can afford a hand‑rolled loop.
- You must process extremely large streams where regex overhead becomes a bottleneck.
Takeaway
Rexx’s native REGEXP is a lightweight, cross‑implementation tool that brings full POSIX regex power to the language. By combining it with SUBSTR and the optional COMP flag, you can build efficient, maintainable parsers without external dependencies. Just be mindful of legacy support, backtracking, and Unicode handling when deploying to production.
Next Steps
- Experiment with more advanced patterns: look‑aheads, backreferences (if supported), and named groups.
- Benchmark against other string‑processing techniques in your specific Rexx environment.
- Document any regexes used in shared scripts to aid future maintenance.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.