Guide · Chapter 5
Text, JSON, and CSV
Process UTF-8 text, regular expressions, and structured data.
String and UTF-8
String is an immutable UTF-8 byte sequence. length counts Unicode code points, byte_length counts encoded bytes, and indexing returns a one-code-point String. Text functions return new values and never mutate the original.
let line = " ERROR: timeout "
line
|> trim
|> replace("ERROR", "WARN")
|> lower
|> printfunctrim#
trim(String) -> StringRemove whitespace from both ends of a String.
funcsplit#
split(String, String) -> List<String>Split a String by delimiter text into List<String>.
funcjoin#
join(List<String>, String) -> StringJoin List<String> with delimiter text.
funcreplace#
replace(String, String, String) -> StringReturn a new String with matching text replaced.
funccontains#
contains(String | List, Value) -> BoolTest whether a String contains a substring or a List contains an equal value.
funcstarts_with#
starts_with(String, String) -> BoolTest whether a String starts with the given text.
funcends_with#
ends_with(String, String) -> BoolTest whether a String ends with the given text.
funclower#
lower(String) -> StringReturn a new String converted to Unicode lowercase.
funcupper#
upper(String) -> StringReturn a new String converted to Unicode uppercase.
Regex
A Regex literal is /pattern/flags with i (case-insensitive), m (multiline), s (dot matches newline), and u. regex_match returns Bool; regex_captures returns the full match, byte positions, numbered groups, and named captures, or null when unmatched.
JSON type mapping and errors
read_text(path("users.json"))
|> parse_json
|> get("users")
|> stream
|> where { user -> user.active == true }
|> collect
|> encode_json({ pretty: true })
|> save_text(path("active-users.json"))| JSON | HHY |
|---|---|
| object | Map |
| array | List |
| string | String |
| integer | Int |
| decimal | Float |
| true / false | Bool |
| null | Null |
parse_json reports line and column on failure. encode_json accepts { pretty: true } for readable output. Function, Stream, and system objects require mapping to ordinary fields first.
CSV is a record stream
parse_csv accepts a complete String or Stream<String> and returns Stream<Map>; encode_csv accepts Stream<Map> and returns Stream<String> records without terminators. Neither requires a whole-file buffer.
read_lines(path("employees.csv"))
|> parse_csv({ header: true })
|> where { row -> row.active == "true" }
|> encode_csv({ header: true })
|> save_lines(path("active-employees.csv"))header controls field names; delimiter and quote must be single characters. CSV performs no schema inference, so numbers and Bools require explicit conversion. encode_csv omits terminators and composes with save_lines.
