Menu

Regex

Regex values represent regular expressions. They are created from literals (/pattern/flags) or the regex() builtin, and are used for matching, replacing, and splitting strings.

Literals

let r = /hello/
let digits = /\d+/
let email = /\w+@\w+\.\w+/i

Flags follow the closing /:

Flag Meaning
i Case-insensitive
m Multi-line (^ and $ match line boundaries)
s Dotall (. matches newline)
g Global (match all occurrences — used by operators and methods)
let r = /pattern/igs              // multiple flags

regex() Builtin

Create a regex from strings — useful when the pattern is dynamic:

let r = regex("\\d+", "g")
let pattern = "hello"
let r2 = regex(pattern, "i")

⚠️ Backslashes must be doubled in strings ("\\d+") but not in literals (/\d+/). Prefer literals for static patterns.

Match Operator — ~

The ~ operator tests a string against a regex and returns an array of matches (or null if no match). Element [0] is the full match; subsequent elements are capture groups:

"hello123" ~ /(\w+?)(\d+)/      // ["hello123", "hello", "123"]
"no match" ~ /\d+/              // null

Because null is falsy and a match array is truthy, ~ works directly in conditions:

if ("test@example.com" ~ /\w+@\w+/) {
    "valid-ish email"
}

Extracting Captures

let m = "2026-02-06" ~ /(\d{4})-(\d{2})-(\d{2})/
m[0]                             // "2026-02-06"
m[1]                             // "2026"
m[2]                             // "02"
m[3]                             // "06"

Not-Match Operator — !~

Returns true when the string does not match:

"hello" !~ /\d+/                 // true
"hello123" !~ /\d+/              // false

Properties

Property Type Description
.pattern string The regex pattern string
.flags string The flag characters
let r = /\d+/gi
r.pattern                        // "\\d+"
r.flags                          // "gi"

Methods

.test(str)

Returns true if the pattern matches anywhere in the string:

let digits = /\d+/
digits.test("hello123")          // true
digits.test("hello")             // false

.replace(str, replacement)

Replace matches in a string. Without g flag, replaces only the first match. With g, replaces all:

let r = /\d+/g
r.replace("abc123def456", "X")   // "abcXdefX"

let first = /\d+/
first.replace("abc123def456", "X")  // "abcXdef456"

Replacement can be a function that receives the match and returns the replacement:

let r = /[a-z]+/g
r.replace("hello WORLD", fn(m) { m.toUpper() })
// "HELLO WORLD"

.format(style?)

Format the regex for display:

let r = /\d+/g
r.format()                       // "/\\d+/g"
r.format("pattern")              // "\\d+"
r.format("verbose")              // pattern and flags separately

.toDict() / .inspect()

let r = /\d+/gi
r.toDict()                       // {pattern: "\\d+", flags: "gi"}
r.inspect()                      // {__type: "regex", pattern: "\\d+", flags: "gi"}

String Methods with Regex

Several string methods accept regex arguments:

"hello world" ~ /wo\w+/         // ["world"]

"abc123def".replace(/\d+/, "X")     // "abcXdef" (first match)
"abc123def456".replace(/\d+/g, "X") // "abcXdefX" (g flag: all matches)

⚠️ .split() takes a string separator only — it does not accept a regex.

The .replace() string method also supports function replacement:

"hello world".replace(/\w+/g, fn(m) { m.toTitle() })
// "Hello World"

Common Patterns

Validation

let isEmail = fn(s) { s ~ /^[\w.+-]+@[\w-]+\.[\w.]+$/ != null }
let isNumeric = fn(s) { s ~ /^\d+$/ != null }

Extract All Matches

Use the g flag with ~:

let text = "Call 555-1234 or 555-5678"
let numbers = text ~ /\d{3}-\d{4}/g
// ["555-1234", "555-5678"]

With capture groups, each match is a [full, group1, …] array; with named groups, each match is a dictionary.

Named Capture Groups

Go-style named captures with (?P<name>...):

let m = "2026-02-06" ~ /(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})/
m.year                          // "2026" — named groups return a dictionary
m.month                         // "02"
m["0"]                          // full match: "2026-02-06"

Search and Replace

let clean = /\s+/g
clean.replace("  too   many   spaces  ", " ")
// " too many spaces "

Key Differences from Other Languages

  • ~ returns an array or null — not a boolean. Use !~ for a boolean "does not match" test, or check != null for "does match" as a boolean.
  • g flag controls global matching — without it, ~ and .replace() operate on the first match only.
  • No regex literal in arbitrary expression position — regex literals must be assigned to a variable or used on the right side of ~ / !~. Use regex() for dynamic patterns.
  • Go regex engine — Parsley uses Go's regexp package (RE2 syntax). No backreferences, no lookahead/lookbehind.
  • Named groups use (?P<name>...) — the Go/Python syntax, not the JavaScript (?<name>...) syntax.

See Also