String Operators
String manipulation and searching operations.
Feature flags (Rust crate).
cat,substr, andinare baseline.length,starts_with,ends_with,upper,lower,trim, andsplitrequire theext-stringfeature. Every language binding enables all operator features, so this only affects the Rust crate. See the feature table.
Argument counts: cat takes any number of arguments; substr one to three; in, starts_with, ends_with and split two; length, upper, lower and trim one. With too few arguments, substr returns "", in returns false, and the others raise Invalid Arguments. Extra arguments are ignored, except by length, which raises Invalid Arguments.
substr, starts_with, ends_with, upper, lower, trim and split convert a non-string argument to its string form first: 12 becomes "12" and null becomes "".
cat
Concatenate strings together.
Syntax:
{ "cat": [a, b, ...] }
Arguments:
a,b, … - Values to concatenate (variadic)
Returns: Concatenated string. Numbers and booleans add their text, null adds nothing, and an array argument adds each of its items.
Examples:
// Simple concatenation
{ "cat": ["Hello", " ", "World"] }
// Result: "Hello World"
// With variables
{ "cat": ["Hello, ", { "var": "name" }, "!"] }
// Data: { "name": "Alice" }
// Result: "Hello, Alice!"
// Non-strings are converted
{ "cat": ["Value: ", 42] }
// Result: "Value: 42"
{ "cat": ["Is active: ", true] }
// Result: "Is active: true"
// Building paths
{ "cat": ["/users/", { "var": "userId" }, "/profile"] }
// Data: { "userId": 123 }
// Result: "/users/123/profile"
Try it:
substr
Extract a substring.
Syntax:
{ "substr": [string, start] }
{ "substr": [string, start, length] }
Arguments:
string- Source stringstart- Starting index (0-based, negative counts from end)length- Number of characters (optional, negative counts from end)
A start or length that is not an integer counts as absent: { "substr": ["abcdef", 1.5] } is "abcdef".
Returns: Extracted substring.
Examples:
// From start index
{ "substr": ["Hello World", 0, 5] }
// Result: "Hello"
// From middle
{ "substr": ["Hello World", 6] }
// Result: "World"
// Negative start (from end)
{ "substr": ["Hello World", -5] }
// Result: "World"
// Negative length (exclude from end)
{ "substr": ["Hello World", 0, -6] }
// Result: "Hello"
// Get file extension
{ "substr": ["document.pdf", -3] }
// Result: "pdf"
// With variables
{ "substr": [{ "var": "text" }, 0, 10] }
// Data: { "text": "This is a long string" }
// Result: "This is a "
Try it:
in
Check if a value is contained in a string or array.
Syntax:
{ "in": [needle, haystack] }
Arguments:
needle- Value to search forhaystack- String or array to search in
Returns: true if found, false otherwise.
Examples:
// String contains substring
{ "in": ["World", "Hello World"] }
// Result: true
{ "in": ["xyz", "Hello World"] }
// Result: false
// Array contains element
{ "in": [2, [1, 2, 3]] }
// Result: true
{ "in": [5, [1, 2, 3]] }
// Result: false
// Check membership
{ "in": [{ "var": "role" }, ["admin", "moderator"]] }
// Data: { "role": "admin" }
// Result: true
// Check substring
{ "in": ["@", { "var": "email" }] }
// Data: { "email": "user@example.com" }
// Result: true
Try it:
Notes:
- A string haystack requires a string needle:
{ "in": [2, "123"] }isfalse; the engine never stringifies numbers for substring search - Array membership uses strict deep equality (the same predicate as
distinct):{ "in": ["2", [1, 2, 3]] }isfalse, while{ "in": [1, [1.0, 2]] }istrueand nested arrays/objects compare structurally - Any other haystack (an object,
null, a missing variable) yieldsfalse, as does a missing haystack argument
length
Get the length of a string or array.
Syntax:
{ "length": value }
Arguments:
value- String or array
Returns: Length (number of characters or elements).
Examples:
// String length
{ "length": "Hello" }
// Result: 5
// Array length (pass a value that resolves to an array)
{ "length": { "var": "nums" } }
// Data: { "nums": [1, 2, 3, 4, 5] }
// Result: 5
// Empty string
{ "length": "" }
// Result: 0
// Empty array (data-driven)
{ "length": { "var": "empty" } }
// Data: { "empty": [] }
// Result: 0
// With variables
{ "length": { "var": "items" } }
// Data: { "items": ["a", "b", "c"] }
// Result: 3
// Check minimum length
{ ">=": [{ "length": { "var": "password" } }, 8] }
// Data: { "password": "secret123" }
// Result: true
Notes:
lengthtakes exactly one argument. The engine parses a literal array such as{ "length": [1, 2, 3] }as a multi-argument call, which throws Invalid Arguments. Pass a single value that resolves to an array (for example{ "length": { "var": "items" } }), or wrap the literal in one more array:{ "length": [[1, 2, 3]] }is3.lengthaccepts only strings and arrays:null(including a missingvar), numbers, booleans, and objects throw Invalid Arguments. Guard optional fields with??, for example{ "length": { "??": [{ "var": "items" }, []] } }, which is0whenitemsis absent.- String length counts Unicode characters, not bytes (
{ "length": "héllo" }is5).
Try it:
starts_with
Check if a string starts with a prefix.
Syntax:
{ "starts_with": [string, prefix] }
Arguments:
string- String to checkprefix- Prefix to look for
Returns: true if string starts with prefix, false otherwise.
Examples:
{ "starts_with": ["Hello World", "Hello"] }
// Result: true
{ "starts_with": ["Hello World", "World"] }
// Result: false
// Check URL scheme
{ "starts_with": [{ "var": "url" }, "https://"] }
// Data: { "url": "https://example.com" }
// Result: true
// Case sensitive
{ "starts_with": ["Hello", "hello"] }
// Result: false
Try it:
ends_with
Check if a string ends with a suffix.
Syntax:
{ "ends_with": [string, suffix] }
Arguments:
string- String to checksuffix- Suffix to look for
Returns: true if string ends with suffix, false otherwise.
Examples:
{ "ends_with": ["Hello World", "World"] }
// Result: true
{ "ends_with": ["Hello World", "Hello"] }
// Result: false
// Check file extension
{ "ends_with": [{ "var": "filename" }, ".pdf"] }
// Data: { "filename": "report.pdf" }
// Result: true
// Case sensitive
{ "ends_with": ["test.PDF", ".pdf"] }
// Result: false
Try it:
upper
Convert string to uppercase.
Syntax:
{ "upper": string }
Arguments:
string- String to convert
Returns: Uppercase string.
Examples:
{ "upper": "hello" }
// Result: "HELLO"
{ "upper": "Hello World" }
// Result: "HELLO WORLD"
// With variable
{ "upper": { "var": "name" } }
// Data: { "name": "alice" }
// Result: "ALICE"
// Unicode case mapping can change the length
{ "upper": "straße" }
// Result: "STRASSE"
Try it:
lower
Convert string to lowercase.
Syntax:
{ "lower": string }
Arguments:
string- String to convert
Returns: Lowercase string.
Examples:
{ "lower": "HELLO" }
// Result: "hello"
{ "lower": "Hello World" }
// Result: "hello world"
// Case-insensitive comparison
{ "==": [
{ "lower": { "var": "input" } },
"yes"
]}
// Data: { "input": "YES" }
// Result: true
// Context-sensitive rules: a final Greek capital sigma becomes ς
{ "lower": "ΟΔΟΣ" }
// Result: "οδος"
Try it:
Notes:
upperandlowerapply Unicode’s full case mappings (Rust’sstr::to_uppercase/str::to_lowercase), context-sensitive rules such as the Greek final sigma included
trim
Remove leading and trailing whitespace.
Syntax:
{ "trim": string }
Arguments:
string- String to trim
Returns: String with whitespace removed from both ends.
Examples:
{ "trim": " hello " }
// Result: "hello"
{ "trim": "\n\ttext\n\t" }
// Result: "text"
// Clean user input
{ "trim": { "var": "userInput" } }
// Data: { "userInput": " search query " }
// Result: "search query"
Try it:
split
Split a string into an array.
Syntax:
{ "split": [string, delimiter] }
Arguments:
string- String to splitdelimiter- Delimiter to split on
Returns: Array of substrings.
Examples:
// Split by space
{ "split": ["Hello World", " "] }
// Result: ["Hello", "World"]
// Split by comma
{ "split": ["a,b,c", ","] }
// Result: ["a", "b", "c"]
// Split by empty string (characters)
{ "split": ["abc", ""] }
// Result: ["a", "b", "c"]
// Parse CSV-like data
{ "split": [{ "var": "tags" }, ","] }
// Data: { "tags": "rust,json,logic" }
// Result: ["rust", "json", "logic"]
// Split an email address
{ "split": ["user@example.com", "@"] }
// Result: ["user", "example.com"]
Try it:
Notes:
splitreads exactly two arguments. There is no limit argument:{ "split": ["a,b,c,d", ",", 2] }still returns all four parts, and a single argument is Invalid Arguments- An empty input string gives
[""]
See Also
- Array Operators (
slice,merge,map,filter): slice and transform arrays produced bysplit - Comparison Operators (
==,===): compare strings lexicographically or with type coercion - Operators Overview: full operator table and feature flags