yq Session 02: Filters

Building on basics. This session covers filtering YAML data with select, checking for keys with has, and navigating paths.

Pre-Session State

  • Can access YAML properties with .key

  • Can iterate sequences with .[]

  • Know -o=json for JSON output

Setup

cat > /tmp/yq-hosts.yaml << 'EOF'
hosts:
  - name: kvm-01
    ip: 10.50.1.110
    role: hypervisor
    active: true
    vlans: [10, 50, 99]
  - name: kvm-02
    ip: 10.50.1.111
    role: hypervisor
    active: true
    vlans: [10, 50]
  - name: vault-01
    ip: 10.50.1.60
    role: secrets
    active: true
    vlans: [50]
  - name: vault-02
    ip: 10.50.1.61
    role: secrets
    active: false
    vlans: [50]
  - name: ise-01
    ip: 10.50.1.20
    role: nac
    active: true
    vlans: [10, 50, 99]
EOF

Lesson 1: Select

Concept: select(condition) keeps items matching the condition. Same as jq.

Exercise 1.1: Filter by role

yq '.hosts[] | select(.role == "hypervisor")' /tmp/yq-hosts.yaml

Output: Only kvm-01 and kvm-02 entries.

Exercise 1.2: Filter by boolean

yq '.hosts[] | select(.active == false) | .name' /tmp/yq-hosts.yaml

Output: vault-02

Exercise 1.3: Filter with contains

yq '.hosts[] | select(.name == "ise*") | .ip' /tmp/yq-hosts.yaml

Note: yq uses == with glob patterns, not contains() like jq. For substring matching:

yq '.hosts[] | select(.name | test("vault")) | .ip' /tmp/yq-hosts.yaml

Lesson 2: Has

Concept: has("key") checks if a key exists in a mapping.

Exercise 2.1: Check for key

yq '.hosts[0] | has("vlans")' /tmp/yq-hosts.yaml

Output: true

Exercise 2.2: Filter by key existence

cat > /tmp/yq-mixed.yaml << 'EOF'
services:
  - name: vault
    port: 8200
    tls: true
  - name: consul
    port: 8500
  - name: prometheus
    port: 9090
    tls: true
EOF
yq '.services[] | select(has("tls")) | .name' /tmp/yq-mixed.yaml

Output: vault, prometheus

Lesson 3: Keys and Entries

Concept: Extract structure from mappings.

Exercise 3.1: Get all keys

yq '.hosts[0] | keys' /tmp/yq-hosts.yaml

Output: Sequence of key names.

Exercise 3.2: Convert to entries

yq '.hosts[0] | to_entries' /tmp/yq-hosts.yaml

Output: Array of {key: …​, value: …​} pairs.

Exercise 3.3: From entries (round-trip)

yq '.hosts[0] | to_entries | from_entries' /tmp/yq-hosts.yaml

Output: Original mapping reconstructed.

Lesson 4: Path

Concept: path() shows the path to a value in the document tree.

Exercise 4.1: Find a path

yq '.hosts[0].name | path' /tmp/yq-hosts.yaml

Output: The path as a sequence of keys and indices.

Exercise 4.2: Use paths for exploration

yq '[.. | path | join(".")]' /tmp/yq-mixed.yaml

Shows every path in the document. Useful for understanding structure.

Lesson 5: Map and Collect

Concept: map() applies a filter to every element. Wrap with [] to collect.

Exercise 5.1: Extract all names

yq '[.hosts[] | .name]' /tmp/yq-hosts.yaml

Output: Sequence of all hostnames.

Exercise 5.2: Map with select

yq '[.hosts[] | select(.active) | .name]' /tmp/yq-hosts.yaml

Output: Only active hostnames.

Summary: What You Learned

Concept Syntax Example

Select

select(cond)

select(.role == "nac")

Test

test(regex)

select(.name | test("vault"))

Has

has("key")

select(has("tls"))

Keys

keys

.hosts[0] | keys

Entries

to_entries

Key-value pair decomposition

Path

path

Show document path to value

Collect

[…​ | filter]

[.hosts[] | .name]

Exercises to Complete

  1. [ ] Get IPs of all active hosts

  2. [ ] Find hosts that have VLAN 99 in their vlans list

  3. [ ] Count hosts per role

  4. [ ] Get all unique VLANs across all hosts

Next Session

Session 03: Editing - In-place edits, merge, delete.

Session Log

Timestamp Notes

Start

<Record when you started>

End

<Record when you finished>