Skip to content

yq Cheatsheet - YAML/JSON/XML Processor

yq Cheatsheet - YAML/JSON/XML Processor

Installation

PlatformCommand
Ubuntu/Debianwget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq
Ubuntu (PPA)sudo add-apt-repository ppa:rmescandon/yq && sudo apt update && sudo apt install yq
macOS (Homebrew)brew install yq
macOS (MacPorts)sudo port install yq
Windows (Chocolatey)choco install yq
Windows (Scoop)scoop install yq
Snapsnap install yq
Gogo install github.com/mikefarah/yq/v4@latest
Dockerdocker run --rm -v "${PWD}":/workdir mikefarah/yq
Alpine Linuxapk add yq
Arch Linuxyay -S yq
Verify Installationyq --version

Basic Commands - Reading & Displaying

CommandDescription
yq '.' file.yamlDisplay entire YAML file (pretty print)
yq '.name' file.yamlRead a specific field value
yq '.metadata.name' file.yamlRead nested field using dot notation
yq '.items[0]' file.yamlAccess first element of an array
yq '.items[*]' file.yamlAccess all elements of an array
yq '.items[]' file.yamlIterate through array elements
yq '.items[].name' file.yamlExtract specific field from all array elements
yq '.items[-1]' file.yamlAccess last element of an array
yq '.items[1:3]' file.yamlArray slice (elements 1 and 2)
cat file.yaml | yq '.spec'Read from stdin
yq -r '.name' file.yamlOutput raw string (no quotes)
yq '.items | length' file.yamlGet array or object length
yq 'keys' file.yamlList all top-level keys
yq '.[] | keys' file.yamlList keys of nested objects

Basic Commands - Writing & Updating

CommandDescription
yq '.name = "new-value"' file.yamlUpdate a field (prints to stdout)
yq -i '.name = "new-value"' file.yamlUpdate field in-place (modifies file)
yq '.spec.replicas = 3' file.yamlUpdate nested value
yq '.items[0].name = "updated"' file.yamlUpdate array element
yq '.newField = "value"' file.yamlCreate new field
yq '.metadata.labels.env = "prod"' file.yamlCreate nested field
yq 'del(.fieldName)' file.yamlDelete a field
yq 'del(.metadata.annotations)' file.yamlDelete nested field
yq 'del(.items[0])' file.yamlDelete array element
yq '.items += {"name": "new"}' file.yamlAppend to array
yq '.items = []' file.yamlClear array
yq '.count += 1' file.yamlIncrement numeric value
yq '.total = .price * .quantity' file.yamlArithmetic operations

Advanced Usage - Filtering & Selection

CommandDescription
yq '.items[] | select(.kind == "Pod")' file.yamlFilter items by condition
yq '.items[] | select(.kind == "Pod" and .status == "Running")' file.yamlMultiple conditions (AND)
yq '.items[] | select(.kind == "Pod" or .kind == "Service")' file.yamlMultiple conditions (OR)
yq '.items[] | select(.name | test("^prod-"))' file.yamlPattern matching with regex
yq '.items[] | select(has("metadata"))' file.yamlCheck if field exists
yq '.items[] | select(.replicas > 3)' file.yamlNumeric comparison
yq '.items[] | select(.tags | contains(["prod"]))' file.yamlArray contains check
yq '.items[] | select(.name != null)' file.yamlFilter out null values
yq '.[] | select(tag == "!!str")' file.yamlFilter by YAML tag type

Advanced Usage - Array Operations

CommandDescription
yq '.items |= sort_by(.name)' file.yamlSort array by field
yq '.items |= sort_by(.metadata.creationTimestamp)' file.yamlSort by nested field
yq '.items |= reverse' file.yamlReverse array order
yq '.tags | unique' file.yamlGet unique array values
yq '.items | flatten' file.yamlFlatten nested arrays
yq '.items | group_by(.kind)' file.yamlGroup array elements
yq '.items | map(.name)' file.yamlMap array to extract values
yq '.items | map(select(.active))' file.yamlFilter and map combined
yq '.items = .items + .newItems' file.yamlConcatenate arrays
yq '.items |= unique_by(.name)' file.yamlRemove duplicates by field
yq '[.items[].name]' file.yamlCollect values into new array

Advanced Usage - Merging & Combining

CommandDescription
yq ea 'select(fi == 0) * select(fi == 1)' f1.yaml f2.yamlDeep merge two files (f2 overrides f1)
yq ea '. as $item ireduce ({}; . * $item)' *.yamlMerge multiple files
yq ea 'select(fi == 0) *+ select(fi == 1)' f1.yaml f2.yamlMerge with array concatenation
yq ea '[.]' file1.yaml file2.yamlCombine files into array
yq '.config = load("config.yaml")' file.yamlLoad and merge external file
yq '.spec.template = load("template.yaml").spec' file.yamlLoad specific path from file
yq ea 'select(fi == 0) *d select(fi == 1)' f1.yaml f2.yamlDeep merge with deletion

Advanced Usage - String Operations

CommandDescription
yq '.fullName = .firstName + " " + .lastName' file.yamlString concatenation
yq '.name |= upcase' file.yamlConvert to uppercase
yq '.name |= downcase' file.yamlConvert to lowercase
yq '.name |= trim' file.yamlTrim whitespace
yq '.text |= sub("old", "new")' file.yamlReplace first occurrence
yq '.text |= gsub("old", "new")' file.yamlReplace all occurrences
yq '.path | split("/")' file.yamlSplit string into array
yq '.tags | join(", ")' file.yamlJoin array into string
yq '.name | length' file.yamlString length
yq '.text | contains("substring")' file.yamlCheck if string contains substring

Advanced Usage - Format Conversion

CommandDescription
yq -o=json '.' file.yamlConvert YAML to JSON
yq -P '.' file.jsonConvert JSON to YAML
yq -o=xml '.' file.yamlConvert YAML to XML
yq -p=xml '.' file.xmlConvert XML to YAML
yq -o=csv '.items[]' file.yamlConvert YAML to CSV
yq -o=props '.' file.yamlConvert YAML to properties format
yq -o=json -I=4 '.' file.yamlJSON with custom indentation
yq -o=yaml --yaml-output-version=1.1 '.' file.yamlSpecify YAML version
yq -p=csv -o=json '.' file.csvConvert CSV to JSON via YAML

Configuration

Command-Line Options

# Input/Output format options
-p, --input-format string    Input format (yaml/json/xml/csv/props)
-o, --output-format string   Output format (yaml/json/xml/csv/props)
-P, --prettyPrint           Pretty print (shorthand for -o=yaml)

# Modification options
-i, --inplace               Edit file in place
-I, --indent int            Indentation (default 2)

# Processing options
-e, --exit-status           Exit with status code based on result
-n, --null-input            Don't read input, start with null
-N, --no-colors             Disable colored output
-C, --colors                Force colored output

# Multiple file options
ea, eval-all                Evaluate all files together

Expression Syntax

# Basic path expressions
.field                      # Access field
.nested.field              # Nested access
.[0]                       # Array index
.[]                        # Array iteration
.*                         # All fields

# Operators
=                          # Assignment
|=                         # Update assignment
+=                         # Append/increment
*                          # Multiply/merge
+                          # Add/concatenate
-                          # Subtract
//                         # Alternative operator (default value)

# Functions
select()                   # Filter
map()                      # Transform array
has()                      # Check existence
keys                       # Get keys
length                     # Get length
sort_by()                  # Sort array
group_by()                 # Group array
unique                     # Remove duplicates

Environment Variables

# Use environment variables in expressions
export APP_NAME="my-app"
yq '.name = env(APP_NAME)' file.yaml

# With default value
yq '.name = (env(NAME) // "default")' file.yaml

# String interpolation
yq '.message = "Hello " + env(USER)' file.yaml

Common Use Cases

Use Case 1: Update Kubernetes Deployment Replicas

# Single deployment
yq -i '.spec.replicas = 5' deployment.yaml

# Multiple deployments in one file
yq -i '(.spec.replicas | select(. != null)) = 5' deployments.yaml

# Conditionally update specific deployment
yq -i '(select(.metadata.name == "api-server") | .spec.replicas) = 10' deployment.yaml

# Update all deployments in multiple files
yq -i '.spec.replicas = 3' k8s/*.yaml

Use Case 2: Merge Configuration Files

# Merge base config with environment-specific overrides
yq ea 'select(fi == 0) * select(fi == 1)' base-config.yaml prod-config.yaml > final-config.yaml

# Merge multiple environment files
yq ea '. as $item ireduce ({}; . * $item)' base.yaml dev.yaml local.yaml > merged.yaml

# Merge with array concatenation
yq ea 'select(fi == 0) *+ select(fi == 1)' config1.yaml config2.yaml > combined.yaml

Use Case 3: Extract and Transform Data

# Extract all container images from Kubernetes manifests
yq '.spec.template.spec.containers[].image' deployment.yaml

# Get all service names and ports
yq '.items[] | select(.kind == "Service") | .metadata.name + ":" + (.spec.ports[0].port | tostring)' services.yaml

# Create summary report
yq '.items[] | {"name": .metadata.name, "kind": .kind, "namespace": .metadata.namespace}' resources.yaml -o=json

Use Case 4: Bulk Updates Across Multiple Files

# Add label to all resources
find . -name "*.yaml" -exec yq -i '.metadata.labels.environment = "production"' {} \;

# Update image tag in all deployments
yq -i '(.spec.template.spec.containers[].image | select(. == "*:latest")) |= sub(":latest", ":v1.2.3")' k8s/**/*.yaml

# Add annotation to specific resources
yq -i 'select(.kind == "Service") | .metadata.annotations."prometheus.io/scrape" = "true"' *.yaml

Use Case 5: CI/CD Pipeline Configuration

# Update version in multiple config files
export VERSION="2.1.0"
yq -i '.version = env(VERSION)' chart/Chart.yaml
yq -i '.image.tag = env(VERSION)' values.yaml

# Inject secrets from environment
yq -i '.database.password = env(DB_PASSWORD)' config.yaml

# Generate environment-specific configs
for env in dev staging prod; do
  yq ea 'select(fi == 0) * select(fi == 1)' base.yaml "env-${env}.yaml" > "config-${env}.yaml"
done

Best Practices

  • Always test without -i first: Run commands without the in-place flag to preview changes before modifying files

    yq '.spec.replicas = 5' deployment.yaml  # Preview first
    yq -i '.spec.replicas = 5' deployment.yaml  # Then apply
  • Use version control: Commit files before bulk modifications to easily revert if needed

  • Quote expressions: Use single quotes for expressions to prevent shell interpretation

    yq '.items[] | select(.name == "test")' file.yaml  # Correct
  • Validate YAML after modifications: Ensure your changes produce valid YAML

    yq '.' modified.yaml > /dev/null && echo "Valid YAML" || echo "Invalid YAML"
  • Use select() for conditional updates: More precise than updating everything

    yq '(select(.kind == "Deployment") | .spec.replicas) = 3' file.yaml
  • Preserve comments: yq preserves comments by default, but be careful with complex transformations

  • Use eval-all for multi-file operations: More efficient than processing files separately

    yq ea '. as $item ireduce ({}; . * $item)' *.yaml
  • Leverage environment variables: Keep sensitive data out of scripts

    export SECRET_KEY="..."
    yq '.apiKey = env(SECRET_KEY)' config.yaml
  • Use raw output for scripting: Use -r flag when piping to other commands

    IMAGE=$(yq -r '.spec.template.spec.containers[0].image' deployment.yaml)
  • Check exit codes for validation: Use -e flag to fail on null/false results

    yq -e '.spec.replicas > 0' deployment.yaml && echo "Valid" || echo "Invalid"

Troubleshooting

IssueSolution
Error: “bad file descriptor”Use -i flag correctly or redirect output: yq '.' file.yaml > temp && mv temp file.yaml
Changes not persistedAdd -i flag for in-place editing: yq -i '.field = "value"' file.yaml
”null” appears in outputField doesn’t exist or is null. Use alternative operator: yq '.field // "default"' file.yaml
Comments are removedUse ... comments="" to explicitly remove, or check if using operations that don’t preserve comments
Array merge replaces instead of concatenatesUse *+ instead of * for merge: yq ea 'select(fi==0) *+ select(fi==1)' f1.yaml f2.yaml
”Error: bad expression”Check expression syntax, ensure proper quoting, verify operators are correct
Output has extra quotesUse -r flag for raw output: yq -r '.name' file.yaml
Cannot process multiple filesUse ea (eval-all) command: yq ea '.' file1.yaml file2.yaml
Wrong version of yqVerify you have mikefarah/yq (not kislyuk/yq): yq --version should show github.com/mikefarah/yq
Permission denied on -iEnsure write permissions: chmod u+w file.yaml or run with appropriate privileges
Encoding issues with special charactersEnsure UTF-8 encoding: yq --encoding=utf-8 '.' file.yaml
Large files cause memory issuesProcess in chunks or use streaming: yq -N '.items[]' large-file.yaml
Path not found errorsVerify path exists: yq 'has("path.to.field")' file.yaml before accessing
Merge conflicts with complex structuresUse explicit merge strategies: *d for deep merge with deletion, *+ for array concatenation

Quick Reference - Common Patterns

# Read value
yq '.path.to.field' file.yaml

# Update value
yq -i '.path.to.field = "new-value"' file.yaml

# Delete field
yq -i 'del(.path.to.field)' file.yaml

# Filter array
yq '.items[] | select(.name == "target")' file.yaml

# Merge files
yq ea 'select(fi==0) * select(fi==1)' base.yaml override.yaml

# Convert format
yq -o=json '.' file.yaml

# Use environment variable
yq '.field = env(VAR_NAME)' file.yaml

# Multiple operations
yq -i '.field1 = "value1" | .field2 = "value2"' file.yaml