Skip to content

Data Processing: jq, yq & xan

jq, yq, and xan for JSON, YAML, and CSV processing.


JSON processor. Reads JSON from files or pipeline input, applies a filter expression, and outputs the results.

jq [OPTIONS] FILTER [FILE...]
FlagDescription
-rRaw output — strings are printed without quotes
-cCompact output — no whitespace or newlines in JSON
-SSort object keys alphabetically
-sSlurp — read all inputs into a single array before filtering

jq uses a path-based filter language to navigate and transform JSON.

ExpressionDescription
.Identity — returns the entire input
.fieldAccess a top-level field
.field.nestedAccess nested fields
.[0]Access array element by index
.[-1]Access array element from the end
.[]Iterate all elements of an array or values of an object
FunctionDescription
keysArray of keys (sorted) from an object, or indices from an array
valuesArray of values from an object or array
lengthNumber of elements in an array/object, or character count of a string
typeType name: "string", "number", "boolean", "array", "object", or "null"
map(expr)Apply expr to each element of an array, return the results as an array
select(expr)Keep the input if expr is truthy, discard it otherwise
notBoolean negation

Use | to chain filters. The output of the left side becomes the input of the right side:

.[] | .name

Use , to produce multiple outputs from a single input:

.name, .age

Build new objects from the input:

{name: .user.name, id: .user.id}

Collect results into an array:

[.[] | .name]

Build strings with embedded expressions:

"Name: \(.name), Age: \(.age)"

select() supports ==, !=, >, <, >=, <=:

.[] | select(.age >= 21)

Each result is a BashObject with BashText set to the formatted JSON string (or raw string with -r).

Extract a nested field:

Terminal window
echo '{"database": {"host": "localhost", "port": 5432}}' | jq '.database.host'
"localhost"

Raw output (no quotes):

Terminal window
echo '{"name": "alice"}' | jq -r '.name'
alice

Iterate array elements:

Terminal window
echo '[1, 2, 3]' | jq '.[]'
1
2
3

Access by index:

Terminal window
echo '["a", "b", "c"]' | jq '.[1]'
"b"

Pipe through filters:

Terminal window
echo '[{"name": "alice"}, {"name": "bob"}]' | jq '.[] | .name'
"alice"
"bob"

Select with a condition:

Terminal window
echo '[{"name": "alice", "age": 30}, {"name": "bob", "age": 17}]' | jq '.[] | select(.age >= 21)'
{
"name": "alice",
"age": 30
}

Map over an array:

Terminal window
echo '[1, 2, 3]' | jq 'map(. * 2)'
[
2,
4,
6
]

Get keys of an object:

Terminal window
echo '{"b": 2, "a": 1, "c": 3}' | jq 'keys'
[
"a",
"b",
"c"
]

Compact output:

Terminal window
echo '{"name": "alice", "age": 30}' | jq -c '.'
{"name":"alice","age":30}

Sort keys:

Terminal window
echo '{"z": 1, "a": 2}' | jq -S '.'
{
"a": 2,
"z": 1
}

Slurp multiple JSON values into an array:

Terminal window
echo '{"a":1}
{"b":2}' | jq -s '.'
[
{
"a": 1
},
{
"b": 2
}
]

Construct a new object:

Terminal window
echo '{"first": "alice", "last": "smith", "age": 30}' | jq '{fullName: "\(.first) \(.last)", age: .age}'
{
"fullName": "alice smith",
"age": 30
}

Read from a file:

Terminal window
jq '.version' package.json

Get the type of a value:

Terminal window
echo '"hello"' | jq 'type'
"string"

YAML processor. Parses YAML input and applies the same filter syntax as jq. Can output as JSON (default) or YAML.

yq [OPTIONS] FILTER [FILE...]
FlagDescription
-rRaw output — strings are printed without quotes
-o FORMATOutput format: json (default) or yaml

yq reuses the full jq filter engine. All filter expressions, built-in functions, pipe expressions, and construction syntax documented under jq work identically in yq.

Each result is a BashObject with BashText set to the formatted output (JSON or YAML).

Extract a field from YAML:

Terminal window
echo "database:
host: localhost
port: 5432" | yq '.database.host'
"localhost"

Raw output:

Terminal window
echo "name: alice" | yq -r '.name'
alice

Convert YAML to JSON:

Terminal window
echo "name: alice
age: 30
tags:
- admin
- user" | yq '.'
{
"name": "alice",
"age": 30,
"tags": [
"admin",
"user"
]
}

Convert JSON to YAML:

Terminal window
echo '{"name": "alice", "age": 30}' | yq -o yaml '.'
name: alice
age: 30

Filter nested YAML and output as YAML:

Terminal window
echo "services:
web:
port: 8080
db:
port: 5432" | yq -o yaml '.services.web'
port: 8080

Read from a file:

Terminal window
yq '.spec.containers' deployment.yaml

Iterate array elements in YAML:

Terminal window
echo "items:
- name: alpha
- name: beta" | yq '.items[] | .name'
"alpha"
"beta"

CSV toolkit. Provides subcommands for inspecting, querying, and formatting CSV data.

xan [-d DELIMITER] SUBCOMMAND [ARGS...] [FILE]
FlagDescription
-d CHARSet the field delimiter (default: ,)

Print the column names from the CSV header row, one per line.

xan headers [FILE]

Print the number of data rows (excluding the header).

xan count [FILE]

Select specific columns by name. Multiple columns are separated by commas.

xan select COLUMNS [FILE]

Filter rows where any field matches a regex pattern. Outputs matching rows with the header.

xan search PATTERN [FILE]

Pretty-print the CSV as an aligned table.

xan table [FILE]

Each subcommand returns BashObject results:

  • headers: one object per column name
  • count: a single object with the row count
  • select: one object per output line (header + matching rows)
  • search: one object per output line (header + matching rows)
  • table: a single object with the formatted table

List column names:

Terminal window
echo "name,age,city
alice,30,portland
bob,25,seattle" | xan headers
name
age
city

Count rows:

Terminal window
echo "name,age
alice,30
bob,25
carol,35" | xan count
3

Select specific columns:

Terminal window
echo "name,age,city
alice,30,portland
bob,25,seattle" | xan select name,city
name,city
alice,portland
bob,seattle

Search for a pattern:

Terminal window
echo "name,age,city
alice,30,portland
bob,25,seattle
carol,35,portland" | xan search portland
name,age,city
alice,30,portland
carol,35,portland

Pretty-print as a table:

Terminal window
echo "name,age,city
alice,30,portland
bob,25,seattle" | xan table
name age city
alice 30 portland
bob 25 seattle

Use a custom delimiter (TSV):

Terminal window
echo "name age city
alice 30 portland
bob 25 seattle" | xan -d ' ' headers
name
age
city

Read from a file:

Terminal window
xan headers data.csv

Pipeline: select columns then search:

Terminal window
xan select name,city data.csv | xan search portland

Combine JSON and CSV tools in a pipeline:

Terminal window
# Extract names from JSON array, format as CSV
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' | jq -r '.[] | "\(.name),\(.age)"' | xan table