Files
gh-xdg-xdg-claude-context-e…/skills/yq/reference/yq-guide.md
2025-11-30 09:06:54 +08:00

433 lines
8.1 KiB
Markdown

# yq: YAML Query and Extraction
**Goal: Extract specific data from YAML without reading entire file.**
**Note:** This guide assumes `mikefarah/yq` (the most common version). Syntax is similar to jq.
## The Essential Pattern
```bash
yq '.field' file.yml
```
yq defaults to YAML output. Use `-r` for raw output or `-o json` for JSON:
```bash
yq -r '.field' file.yml # Raw string output
yq -o json file.yml # Convert to JSON
```
---
# Core Patterns (80% of Use Cases)
## 1. Extract Top-Level Field
```bash
yq '.version' config.yml
yq '.name' config.yml
```
## 2. Extract Nested Field
```bash
yq '.services.web.image' docker-compose.yml
yq '.jobs.build.steps' .github/workflows/ci.yml
```
## 3. Extract from Array by Index
```bash
yq '.items[0]' file.yml # First element
yq '.jobs.build.steps[2]' ci.yml # Third step
```
## 4. Extract All Array Elements
```bash
yq '.items[]' file.yml # All elements
yq '.services.*.ports' docker-compose.yml # All ports from all services
```
## 5. Extract Field from Each Array Element
```bash
yq '.services.*.image' docker-compose.yml # All service images
yq '.jobs.*.runs-on' .github/workflows/ci.yml # All job runners
```
## 6. Get Object Keys
```bash
yq 'keys' object.yml
yq '.services | keys' docker-compose.yml
```
## 7. Filter Array by Condition
```bash
yq '.items[] | select(.active == true)' file.yml
yq '.services.* | select(.ports)' docker-compose.yml
```
## 8. Extract Specific Array Elements
```bash
yq '.services.web' docker-compose.yml
yq '.jobs.build' .github/workflows/ci.yml
```
## 9. Handle Missing Fields
```bash
yq '.field // "default"' file.yml
```
## 10. Convert YAML to JSON
```bash
yq -o json file.yml
```
---
# Common Real-World Workflows
## Docker Compose
### "List all services"
```bash
yq '.services | keys' docker-compose.yml
```
### "Get image for service"
```bash
yq '.services.web.image' docker-compose.yml
```
### "Get all ports"
```bash
yq '.services.*.ports' docker-compose.yml
```
### "Get environment variables for service"
```bash
yq '.services.api.environment' docker-compose.yml
```
### "Get depends_on for service"
```bash
yq '.services.web.depends_on' docker-compose.yml
```
## GitHub Actions
### "List all jobs"
```bash
yq '.jobs | keys' .github/workflows/ci.yml
```
### "Get build steps"
```bash
yq '.jobs.build.steps' .github/workflows/ci.yml
```
### "Get trigger events"
```bash
yq '.on' .github/workflows/ci.yml
```
### "Get runner for job"
```bash
yq '.jobs.build.runs-on' .github/workflows/ci.yml
```
## Kubernetes
### "Get container image"
```bash
yq '.spec.template.spec.containers[0].image' deployment.yml
```
### "Get replicas"
```bash
yq '.spec.replicas' deployment.yml
```
### "List all container names"
```bash
yq '.spec.template.spec.containers[].name' deployment.yml
```
## Configuration Files
### "Get database host"
```bash
yq '.database.host' config.yml
```
### "Get API key"
```bash
yq '.api.key' config.yml
```
---
# Advanced Patterns (20% Use Cases)
## Combine Multiple Queries
```bash
yq '{version: .version, services: (.services | keys)}' docker-compose.yml
```
## Count Array Length
```bash
yq '.items | length' file.yml
yq '.services | length' docker-compose.yml
```
## Filter and Extract
```bash
yq '.services.* | select(.ports) | .image' docker-compose.yml
```
## Map Array
```bash
yq '[.items[].name]' file.yml
```
## Multi-Document YAML (Multiple --- separated docs)
```bash
yq 'select(document_index == 0)' multi.yml # First document
yq 'select(document_index == 1)' multi.yml # Second document
```
---
# Output Formats
```bash
yq file.yml # YAML output (default)
yq -o json file.yml # JSON output
yq -o yaml file.yml # Explicit YAML output
yq -r '.field' file.yml # Raw output (strings without quotes)
```
**For string fields, use `-r` for raw output (like jq).**
---
# Pipe Composition
yq uses `|` for piping within queries (like jq):
```bash
yq '.services | keys | .[]' docker-compose.yml
```
Can also pipe to shell commands:
```bash
yq '.services | keys' docker-compose.yml | wc -l # Count services
yq '.services.*.image' docker-compose.yml | sort | uniq # Unique images
```
---
# Common Flags
- `-r` - Raw output (strings without quotes)
- `-o FORMAT` - Output format (yaml, json, props, xml, etc.)
- `-i` - In-place edit (DANGEROUS - use carefully)
- `-P` - Pretty print
- `-I INDENT` - Indentation level
**Default to `-r` for string extraction, `-o json` for JSON output.**
---
# YAML-Specific Features
## Anchors and Aliases
YAML supports anchors (&) and aliases (*):
```yaml
default: &default
timeout: 30
production:
<<: *default
host: prod.example.com
```
yq resolves these automatically:
```bash
yq '.production.timeout' file.yml # Returns 30 (from anchor)
```
## Multi-Document YAML
Many YAML files contain multiple documents separated by `---`:
```bash
yq 'select(document_index == 0)' file.yml # First document
yq 'select(document_index == 1)' file.yml # Second document
```
---
# Handling Edge Cases
## If Field Might Not Exist
```bash
yq '.field // "not found"' file.yml
```
## If Array Might Be Empty
```bash
yq '.items[]? // empty' file.yml
```
## Multiple Possible Paths
```bash
yq '.field1 // .field2 // "default"' file.yml
```
---
# Comparison with jq
**Similarities:**
- Similar query syntax (`.field`, `.nested.field`, `.array[]`)
- Pipe operator `|`
- Filter with `select()`
- Default values with `//`
**Differences:**
- yq handles YAML (jq handles JSON)
- yq can output multiple formats (`-o json`, `-o yaml`)
- yq handles YAML features (anchors, multi-doc)
- Slightly different handling of wildcards (`.*` in yq, similar in jq)
**Converting between formats:**
```bash
yq -o json file.yml | jq '.field' # YAML → JSON → query with jq
jq '.' file.json | yq -P # JSON → pretty YAML
```
---
# Integration with Other Tools
## With ast-grep
```bash
# Get dependencies from YAML, search code for usage
yq '.dependencies | keys' config.yml | while read dep; do
rg -l "$dep"
done
```
## With jq (via JSON conversion)
```bash
yq -o json file.yml | jq '.complex.query'
```
If yq syntax doesn't work, convert to JSON and use jq.
## With Docker Compose
```bash
# Get all service images, then pull them
yq '.services.*.image' docker-compose.yml | xargs -n1 docker pull
```
---
# Best Practices
## 1. Use -r for String Fields
```bash
# BAD: yq '.version' file.yml → may include YAML formatting
# GOOD: yq -r '.version' file.yml → raw string
```
## 2. Use -o json for Complex Queries
If yq query is complex, convert to JSON and use jq:
```bash
yq -o json file.yml | jq '.complex.query'
```
## 3. Test Queries on Small Examples
```bash
echo 'key: value' | yq '.key'
```
## 4. Use // for Defaults
```bash
yq -r '.field // "default"' file.yml
```
## 5. Be Aware of Multi-Document Files
Check if file has multiple documents (look for `---`).
---
# Quick Reference
## Most Common Commands
```bash
# Single field
yq '.field' file.yml
# Nested field
yq '.parent.child' file.yml
# Array element
yq '.array[0]' file.yml
# All array elements
yq '.array[]' file.yml
# Object keys
yq 'keys' file.yml
# Filter array
yq '.array[] | select(.field == "value")' file.yml
# All services (docker-compose)
yq '.services | keys' docker-compose.yml
# Convert to JSON
yq -o json file.yml
# Raw string output
yq -r '.field' file.yml
```
---
# When to Use Read Instead
Use Read tool when:
- File is < 50 lines
- Need to see overall structure
- Making edits (need full context)
- Exploring unknown YAML structure
Use yq when:
- File is large (docker-compose, k8s configs often are)
- You know exactly what field(s) you need
- Want to save context tokens
---
# Summary
**Your default pattern:**
```bash
yq '.field' file.yml
```
**For strings:**
```bash
yq -r '.field' file.yml
```
**For JSON output:**
```bash
yq -o json file.yml
```
**Key principles:**
1. Use `-r` for raw string output
2. Use `.` notation for nested fields
3. Use `[]` for arrays, `[n]` for specific index
4. Use `| keys` for object keys
5. Use `//` for defaults
6. Use `-o json` to convert to JSON if needed
**Massive context savings: Extract only what you need instead of reading entire YAML files.**