Expand

Pattern Matching

Pattern matching is a way to destuct values during an assignment:

[$a, $b, $c] := ["one", "two", "three"]

It's always possible to rewrite pattern matching with standard assignments at the cost of being more verbose:

$list := ["one", "two", "three"]
$a := $list[0]
$b := $list[1]
$c := $list[2]

At the moment, only 3 patterns are supported: list, formatter, and string patterns.

Pattern matching is available at places, when a variable can be defined or assigned, such as in for loops, assigns with := or =, and in function declarations (partly).

List Pattern

Currently, only fixed sized-lists are supported. If length of a pattern list doesn't match length assigned list, then pattern matching fails and panic is created. It also panics, if assigned value is not a list at all.

run some commands for every admin in the system
fn list-users {
    put ["alice", 1, "admin"]
    put ["bob",   2, "admin"]
    put ["eve",   3, "user"]
}

list-users
  | for [$user, _, $role] if $role == "admin" {
      # some commands
  }

Formatter Pattern

Any formater like :json or :colons can be used to parse assigned string before setting it to a variable:

(colons)$fields := "root:x:0:0:Super User:/root:/bin/bash"

The colons formatter splits a given string by colon ':', produced list will be assigned to $fields.

convert /etc/group to jsonl
cat /etc/group
  | for (colons)$g {
      put {
          group: $g[0],
          gid:   $g[2],
          users: $g[3]:commas
      }@json
  }
different pattern types can be combined together; get all non-system user groups
cat /etc/group
  | for (colons)[$group, _, $gid, _] {
      if $gid:int >= 1000 {
          put $group
      }
  }

String Pattern

String pattern allows to do very basic string prefix and suffix trimming. Only one variable is supported.

extract version from a docker image tag
"v$ver" := "bubuntu:v26.04":colons[1]
extract version from a docker image tag (alternative version)
(colons)[_, "v$ver"] := "bubuntu:v26.04"
remove path and extension
$files := [
    "doc/index.md",
    "doc/intro.md",
]
for "doc/$name.md" in $files {
    make rendered/$name.html
}