yq: Handle Multi-Document YAML Files
yq treats each --- separated block as its own document, evaluating per document with eval or all together with eval-all.
Kubernetes manifests routinely bundle several resources with --- separators. yq can edit each one independently, pick one out, or split them into files.
What it does
A --- separator starts a new YAML document. yq eval runs the expression once per document; documentIndex (alias di) gives the zero-based position. select(documentIndex == n) keeps one document; eval-all is needed when an expression must see all documents at once.
Common usage
# edit a field in every document
yq -i '.metadata.namespace = "prod"' manifests.yaml
# keep only the Service document
yq 'select(.kind == "Service")' manifests.yaml
# print which document index each kind is at
yq '[documentIndex, .kind]' manifests.yamlMulti-doc tools
| Expression / flag | What it does |
|---|---|
| --- | Document separator in YAML |
| documentIndex (di) | Zero-based index of the current document |
| select(documentIndex == 0) | Keep the first document |
| -N / --no-doc | Suppress the --- separators in output |
| -s / --split-exp | Split each document into its own file |
| eval-all | Bring all documents into one scope |
In CI
To patch the image in just the Deployment of a bundled manifest: yq -i '(select(.kind=="Deployment") | .spec.template.spec.containers[0].image) = strenv(IMG)' manifests.yaml. The select keeps the edit scoped to the right document.
Common errors in CI
Converting a multi-doc file to JSON yields several top-level JSON objects, which most JSON parsers reject; select a single document or use eval-all with [...]. Output keeping unexpected --- lines means you want -N. Python yq reads only the first document by default unless you slurp, another behavioral tell between the two implementations.