# Regex
`re/*` is the PCRE2-backed regular-expression namespace. Patterns are
ordinary strings, compiled on demand and cached; `re/find` and friends
report match positions in codepoint indices — the same coordinate
system as `len` and `slice` — so results feed straight back into string
operations. The functions are part of the stdlib and need no import.
Regex literals also appear directly in `match` arms; see
Pattern Matching.
## Functions
| Function | Purpose |
|---|---|
| `re/match s pattern` | `true` if the pattern matches anywhere in `s` (search, not full-string) |
| `re/find s pattern` | First match as `%{ :match :start :end :groups }`, or nil |
| `re/find-all s pattern` | List of non-overlapping match maps |
| `re/replace s pattern replacement` | Replace the first match; `$1`, `${name}` backrefs |
| `re/replace-all s pattern replacement` | Replace every match; `$1`, `${name}` backrefs |
| `re/split s pattern` | Split on every match; capture groups are not kept |
| `re/captures s pattern` | List of capture strings (`0` = full match), or nil |
| `re/find-at s pattern offset` | First match at or after codepoint `offset` |
| `re/escape text` | Escape regex metacharacters so `text` matches literally |
| `re/clear-cache` | Free every compiled pattern from the internal cache |
| `re/scan-first s patterns offset` | First of `patterns` (a vector of strings) matching exactly at codepoint `offset`; map with `:index`, or nil |
Notes:
- `re/find` returns `%{ :match ... :start N :end N :groups ... }` with
`:start` / `:end` as codepoint slice coordinates, so
`[chars/slice $s $start $end]` extracts the match text. `:groups` is a
map for named captures (`(?<name>...)`), a vector for positional
groups, and `@{}` when the pattern has no groups.
- `re/captures` returns the full match at index 0 followed by the
positional capture groups. For named captures, use `re/find` — its
`:groups` map is keyed by name.
- `re/match` is a plain search: `[re/match "abc123" "\d+"]` is `true`.
Anchor with `\A...\z` (or `^...$` with the appropriate flags) when you
need a full-string test.
- Invalid patterns do not raise: `re/match` returns `false`, and the
find / replace / split family returns nil.
- `re/scan-first` is anchored: each pattern is tested at the given
offset only (PCRE2 anchored mode), and the lowest pattern index wins.
Advance the offset yourself to tokenise a line — it is the primitive
behind the editor's syntax highlighter.
- Compiled patterns live in a fixed-size per-thread LRU cache, so hot
patterns compile once. `re/clear-cache` drops the whole cache, which
matters in long-running processes that build patterns dynamically.
## Examples
### Validate and locate
# Search semantics — the pattern may match anywhere in the subject echo [re/match "user@example.com" "^\\w+@\\w+\\.\\w{2,}$"] # true set m [re/find "order 1234 shipped" "\\d+"] echo $m~match $m~start $m~end # 1234 6 10 # :start/:end are codepoint indices — slice the match back out echo [chars/slice "order 1234 shipped" $m~start $m~end] # 1234
### Captures
# Positional captures: index 0 is the full match echo [re/captures "2024-01-15" "(\\d+)-(\\d+)-(\\d+)"] # => @{2024-01-15 2024 01 15} # Named captures arrive as a keyword-keyed map on :groups set m [re/find "2024-01-15" "(?<y>\\d+)-(?<m>\\d+)-(?<d>\\d+)"] echo $m~groups~y "-" $m~groups~m "-" $m~groups~d # 2024-01-15
### Replace and split
echo [re/replace "a1b22c" "\\d+" "<$1>"] # a<1>b22c echo [re/replace-all "a1b22c" "\\d+" "#"] # a#b#c echo [re/replace-all "john smith" "(?<f>\\w+) (?<l>\\w+)" "${l}, ${f}"] # => "smith, john" echo [re/split "a1b22c" "\\d+"] # @{a b c} echo [re/escape "a.b*c"] # a\.b\*c
### Anchored tokenising with scan-first
set line "let x = 42" set patterns @{"\\s+" "let" "\\w+" "=" "[0-9]+"} set pos 0 while ($pos < $line(len)) { set hit [re/scan-first $line $patterns $pos] if [nil? $hit] { break } echo $hit~index $hit~match set pos $hit~end }
`re/scan-first` returns the first pattern that matches exactly at
`pos`, letting the caller walk the line token by token.
## See Also
- Pattern Matching — regex patterns in `match`
- Strings — codepoint indexing and slicing
- Chars — single-character classification