expressions
computed values (!expr)
An expression computes a value for each host, such as a list, a number, or true or false.
Syntax
The !expr tag marks an expression in the language of expr (expr-lang.org). Its result keeps its type: a list, a number, a boolean, a map, or a string.
Data
An expression reads these names without a leading dot:
| vars | the variables of the host, with the vars of the recipe step |
| facts | the facts of the host; run winch doc facts |
| host | name, short, address, groups, and vars of the host; address is the name when the host has no address |
| item | the current element in a step with loop |
| match(p) | the hosts that match the host pattern p, with the fields of host |
match(p) reads the inventory, not the --hosts selection. A host from match() has only the vars that need no facts. A default cannot use match().
Where expressions go
Any module argument can be an expression or a template, and so can then. when takes an expression. loop takes a list or an expression.
Operators
| + - * / % ** | arithmetic |
| == != < > <= >= | comparison |
| and or not | logic, also && || ! |
| in | membership in a list or a map |
| contains startsWith endsWith | text tests |
| matches | regular expression test |
| c ? a : b | choice |
| a ?? b | a, or b when a is nil |
| [] ?. | read an element or a key |
| x[i:j] 1..3 | slice and range |
| | | pipe: vars.name | lower() |
Predicates
In a predicate, such as the second argument of filter, # is the element, and .name reads the key name of a map element: filter(vars.users, .uid >= 1000).
Missing values
A missing map key is nil. A module argument whose expression gives null fails the host.
Quoting
Quote a YAML value that starts with a quote, [, {, &, *, or !, or that contains ": " or " #".
When they run
winch evaluates expressions on the machine that runs winch, during the plan. They cannot read the result of a step. winch checks each one when it loads the project: an unknown name or a syntax error is an error. An error while winch evaluates one for a host fails that host. The other hosts go on. $env and now() are errors in every expression.
Functions
| Function | Meaning |
|---|---|
abs | abs(n): the absolute value of the number n. |
all | all(list, pred): true when pred is true for each element. |
any | any(list, pred): true when pred is true for at least one element. |
bitand | bitand(a, b): the bitwise AND of two integers. |
bitnand | bitnand(a, b): the bitwise AND NOT of two integers. |
bitnot | bitnot(a): the bitwise NOT of an integer. |
bitor | bitor(a, b): the bitwise OR of two integers. |
bitshl | bitshl(a, n): a shifted left by n bits. |
bitshr | bitshr(a, n): a shifted right by n bits, with its sign. |
bitushr | bitushr(a, n): a shifted right by n bits, without its sign. |
bitxor | bitxor(a, b): the bitwise XOR of two integers. |
ceil | ceil(n): n rounded up to an integer value. |
concat | concat(a, b, ...): the lists joined into one list. |
count | count(list, pred): the number of elements for which pred is true. |
date | date(s), date(s, layout), or date(s, layout, zone): the time in the text s, such as date("2026-10-30"). |
duration | duration(s): the duration in the text s, such as duration("1h30m"). |
filter | filter(list, pred): the elements for which pred is true: filter(match("all"), .name != host.name). |
find | find(list, pred): the first element for which pred is true, or nil. |
findIndex | findIndex(list, pred): the index of the first element for which pred is true, or -1. |
findLast | findLast(list, pred): the last element for which pred is true, or nil. |
findLastIndex | findLastIndex(list, pred): the index of the last element for which pred is true, or -1. |
first | first(list): the first element, or nil for an empty list. |
flatten | flatten(list): the elements of the list and of its nested lists, in one list. |
float | float(v): the number or the text v as a float. |
floor | floor(n): n rounded down to an integer value. |
fromBase64 | fromBase64(s): the text that the base64 text s encodes. |
fromJSON | fromJSON(s): the value of the JSON text s. |
fromPairs | fromPairs(list): a map from a list of [key, value] pairs. |
get | get(m, key): the value of key in the map m, or nil when m has no such key. |
groupBy | groupBy(list, pred): a map from each result of pred to the list of elements that give it. |
hasPrefix | hasPrefix(s, prefix): true when s starts with prefix. |
hasSuffix | hasSuffix(s, suffix): true when s ends with suffix. |
indexOf | indexOf(s, sub): the index of the first sub in s, or -1. |
int | int(v): the number or the text v as an integer: int("8080"). |
join | join(list, sep): the strings of list joined with sep. |
json | json(v): v as JSON on one line. |
keys | keys(m): the keys of the map m, in sorted order. |
last | last(list): the last element, or nil for an empty list. |
lastIndexOf | lastIndexOf(s, sub): the index of the last sub in s, or -1. |
len | len(x): the length of a string, a list, or a map. |
lower | lower(s): s in lower case. |
map | map(list, pred): the result of pred for each element: map(vars.users, .name). |
match | match(pattern): the hosts that match the host pattern, each with name, short, address, groups, and vars, as host has. |
max | max(a, b, ...), or max(list): the largest number. |
mean | mean(list): the average of the numbers. |
median | median(list): the median of the numbers. |
min | min(a, b, ...), or min(list): the smallest number. |
none | none(list, pred): true when pred is false for each element. |
one | one(list, pred): true when pred is true for exactly one element. |
quote | quote(s): s in single quotes for sh, each ' as '\''. |
reduce | reduce(list, pred, initial): one value from all elements. |
repeat | repeat(s, n): s n times. |
replace | replace(s, old, new): s with each old replaced by new. |
reverse | reverse(list): the elements in reverse order. |
round | round(n): n rounded to the nearest integer value. |
sort | sort(list), or sort(list, "desc"): the elements in ascending or descending order. |
sortBy | sortBy(list, pred), or sortBy(list, pred, "desc"): the elements in the order of the results of pred: sortBy(vars.users, .uid). |
split | split(s, sep), or split(s, sep, n): the parts of s between each sep. |
splitAfter | splitAfter(s, sep), or splitAfter(s, sep, n): the parts of s after each sep, each with sep at its end. |
sqlquote | sqlquote(s): s as a string literal for MariaDB, or for PostgreSQL with E before it: in single quotes, each ' as '', each \ as \\. |
string | string(v): v as text: string(8080) is "8080". |
sum | sum(list), or sum(list, pred): the sum of the numbers, or of the results of pred. |
take | take(list, n): the first n elements. |
timezone | timezone(name): the time zone name, such as "Europe/Berlin", for the In method of a date. |
toBase64 | toBase64(s): s in base64. |
toPairs | toPairs(m): the [key, value] pairs of the map m, in sorted key order. |
trim | trim(s), or trim(s, chars): s without white space, or without the characters in chars, at both ends. |
trimPrefix | trimPrefix(s, prefix): s without prefix at its start. |
trimSuffix | trimSuffix(s, suffix): s without suffix at its end. |
type | type(v): the type of v as text: nil, bool, int, float, string, array, map, time.Time for a date, or time.Duration. |
uniq | uniq(list): the elements without repeats, in their first order. |
upper | upper(s): s in upper case. |
values | values(m): the values of the map m, in the order of its sorted keys. |
expressions.abs
abs(n): the absolute value of the number n.
expressions.all
all(list, pred): true when pred is true for each element. In pred, # is the element, and .name reads the key name of a map element: all(vars.ports, # > 0).
expressions.any
any(list, pred): true when pred is true for at least one element.
expressions.bitand
bitand(a, b): the bitwise AND of two integers.
expressions.bitnand
bitnand(a, b): the bitwise AND NOT of two integers.
expressions.bitnot
bitnot(a): the bitwise NOT of an integer.
expressions.bitor
bitor(a, b): the bitwise OR of two integers.
expressions.bitshl
bitshl(a, n): a shifted left by n bits.
expressions.bitshr
bitshr(a, n): a shifted right by n bits, with its sign.
expressions.bitushr
bitushr(a, n): a shifted right by n bits, without its sign.
expressions.bitxor
bitxor(a, b): the bitwise XOR of two integers.
expressions.ceil
ceil(n): n rounded up to an integer value.
expressions.concat
concat(a, b, ...): the lists joined into one list.
expressions.count
count(list, pred): the number of elements for which pred is true. Without pred, the number of true elements.
expressions.date
date(s), date(s, layout), or date(s, layout, zone): the time in the text s, such as date("2026-10-30"). The layout is a Go time layout. now() is a load error, so a plan does not depend on the clock.
expressions.duration
duration(s): the duration in the text s, such as duration("1h30m").
expressions.filter
filter(list, pred): the elements for which pred is true: filter(match("all"), .name != host.name).
expressions.find
find(list, pred): the first element for which pred is true, or nil.
expressions.findIndex
findIndex(list, pred): the index of the first element for which pred is true, or -1.
expressions.findLast
findLast(list, pred): the last element for which pred is true, or nil.
expressions.findLastIndex
findLastIndex(list, pred): the index of the last element for which pred is true, or -1.
expressions.first
first(list): the first element, or nil for an empty list.
expressions.flatten
flatten(list): the elements of the list and of its nested lists, in one list.
expressions.float
float(v): the number or the text v as a float.
expressions.floor
floor(n): n rounded down to an integer value.
expressions.fromBase64
fromBase64(s): the text that the base64 text s encodes.
expressions.fromJSON
fromJSON(s): the value of the JSON text s.
expressions.fromPairs
fromPairs(list): a map from a list of [key, value] pairs.
expressions.get
get(m, key): the value of key in the map m, or nil when m has no such key. get(list, i) gives the element at the index i, or nil.
expressions.groupBy
groupBy(list, pred): a map from each result of pred to the list of elements that give it.
expressions.hasPrefix
hasPrefix(s, prefix): true when s starts with prefix. The operator startsWith does the same.
expressions.hasSuffix
hasSuffix(s, suffix): true when s ends with suffix. The operator endsWith does the same.
expressions.indexOf
indexOf(s, sub): the index of the first sub in s, or -1.
expressions.int
int(v): the number or the text v as an integer: int("8080").
expressions.join
join(list, sep): the strings of list joined with sep.
expressions.json
json(v): v as JSON on one line. Map keys are in sorted order, and non-ASCII characters stay UTF-8. The output is also a valid YAML value.
expressions.keys
keys(m): the keys of the map m, in sorted order. It cannot read vars itself: name each variable.
expressions.last
last(list): the last element, or nil for an empty list.
expressions.lastIndexOf
lastIndexOf(s, sub): the index of the last sub in s, or -1.
expressions.len
len(x): the length of a string, a list, or a map.
expressions.lower
lower(s): s in lower case.
expressions.map
map(list, pred): the result of pred for each element: map(vars.users, .name).
expressions.match
match(pattern): the hosts that match the host pattern, each with name, short, address, groups, and vars, as host has. It reads the inventory, not the --hosts selection. A host from match() has only the vars that need no facts. It works in steps, not in defaults. A constant pattern that matches no host is a load error.
expressions.max
max(a, b, ...), or max(list): the largest number.
expressions.mean
mean(list): the average of the numbers.
expressions.median
median(list): the median of the numbers.
expressions.min
min(a, b, ...), or min(list): the smallest number.
expressions.none
none(list, pred): true when pred is false for each element.
expressions.one
one(list, pred): true when pred is true for exactly one element.
expressions.quote
quote(s): s in single quotes for sh, each ' as '\''. A value goes into a command as it is. Quote a value that must stay one word: then: !expr '"postmap " + quote(vars.map)'.
expressions.reduce
reduce(list, pred, initial): one value from all elements. In pred, #acc is the value so far, # the element, and #index its index: reduce(vars.sizes, #acc + #, 0).
expressions.repeat
repeat(s, n): s n times.
expressions.replace
replace(s, old, new): s with each old replaced by new.
expressions.reverse
reverse(list): the elements in reverse order.
expressions.round
round(n): n rounded to the nearest integer value.
expressions.sort
sort(list), or sort(list, "desc"): the elements in ascending or descending order.
expressions.sortBy
sortBy(list, pred), or sortBy(list, pred, "desc"): the elements in the order of the results of pred: sortBy(vars.users, .uid).
expressions.split
split(s, sep), or split(s, sep, n): the parts of s between each sep. With n, at most n parts.
expressions.splitAfter
splitAfter(s, sep), or splitAfter(s, sep, n): the parts of s after each sep, each with sep at its end.
expressions.sqlquote
sqlquote(s): s as a string literal for MariaDB, or for PostgreSQL with E before it: in single quotes, each ' as '', each \ as \\. It assumes the default SQL mode, without NO_BACKSLASH_ESCAPES, and a UTF-8 client.
expressions.string
string(v): v as text: string(8080) is "8080".
expressions.sum
sum(list), or sum(list, pred): the sum of the numbers, or of the results of pred.
expressions.take
take(list, n): the first n elements.
expressions.timezone
timezone(name): the time zone name, such as "Europe/Berlin", for the In method of a date.
expressions.toBase64
toBase64(s): s in base64.
expressions.toPairs
toPairs(m): the [key, value] pairs of the map m, in sorted key order.
expressions.trim
trim(s), or trim(s, chars): s without white space, or without the characters in chars, at both ends.
expressions.trimPrefix
trimPrefix(s, prefix): s without prefix at its start.
expressions.trimSuffix
trimSuffix(s, suffix): s without suffix at its end.
expressions.type
type(v): the type of v as text: nil, bool, int, float, string, array, map, time.Time for a date, or time.Duration.
expressions.uniq
uniq(list): the elements without repeats, in their first order.
expressions.upper
upper(s): s in upper case.
expressions.values
values(m): the values of the map m, in the order of its sorted keys.
Example
# winch.yaml
name: demo
hosts:
mail.acme.com: {}
web1.acme.com: {}
vars:
mail_server: false
domain: acme.com
admins: [ann, bob]
mailname: !expr 'vars.mail_server ? vars.domain : host.name'
steps:
- name: Set the mail name
file:
path: /etc/mailname
content: !expr 'vars.mailname + "\n"'
when: !expr vars.mail_server
- name: Add the admins
user:
name: !expr item
groups: [sudo]
loop: !expr sort(vars.admins)
- name: List the other hosts
file:
path: /etc/peers
content: !expr 'join(map(filter(match("all"), .name != host.name), .address), "\n") + "\n"'