Every command below is copied from a real terminal, together with the output it produced. Nothing here needs a configuration file or a plugin.
$ echo '{"services":{"web":{"ports":[8080,8443]}}}' | treesift -c 'services.web.ports[0]'
8080
The * step walks every service, and [] flattens each of
their port lists into one stream.
$ echo '{"services":{"web":{"ports":[8080,8443]},"db":{"ports":[5432]}}}' \
| treesift -c 'services.*.ports[]'
8080
8443
5432
-r prints strings bare, which is what you want when the result is going
into a shell loop rather than onto a screen.
$ cat users.yaml
users:
- name: alice
roles: [admin, dev]
- name: bob
roles: [dev]
$ treesift -rc 'users[].name' users.yaml
alice
bob
A key step applied to a list is distributed over its elements, so this is the same selector as above with less punctuation.
$ treesift -rc 'users.name' users.yaml
alice
bob
Attributes become ordinary keys, and repeated elements become a list, so the same selector shape works here too.
$ echo '<config><server host="a.example"/><server host="b.example"/></config>' \
| treesift -rc 'config.server[].host'
a.example
b.example
With -e the exit status carries the answer, so a script does not have to
inspect the output to find out whether anything matched.
$ echo '{}' | treesift -e 'database.host'
$ echo $?
1
if ! host=$(treesift -re 'database.host' config.yaml); then
echo "no database.host in config.yaml" >&2
exit 1
fi
A malformed document is reported on stderr and exits 2, rather than producing a stack trace that a calling script has to parse.
$ echo '{"a":' | treesift -c 'a'
treesift: could not parse JSON: Expecting value: line 2 column 1 (char 6)
$ echo $?
2
A selector that simply matches nothing is not an error — it prints
nothing and exits 0, unless -e asked otherwise.