Eucalypt by Example
This page presents a collection of worked examples showing how eucalypt solves real-world problems. Each example includes the problem, the eucalypt code, and the expected output.
1. Format Conversion: JSON to YAML
Problem: Convert a JSON configuration file to YAML.
echo '{"database": {"host": "db.example.com", "port": 5432}}' | eu
Output:
database:
host: db.example.com
port: 5432
Eucalypt reads JSON natively and defaults to YAML output. No code needed.
2. Extracting Fields from API Data
Problem: Given a list of users in JSON, extract just their names.
eu -e 'map(.name)' <<'JSON'
[
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"},
{"name": "Charlie", "role": "user"}
]
JSON
Output:
- Alice
- Bob
- Charlie
The _ is an expression anaphor -- _.name means "look up name
in whatever the argument is".
3. Filtering and Transforming Data
Problem: From a list of products, find those over a price threshold and format them.
# products.eu
products: [
{ name: "Widget" price: 9.99 }
{ name: "Gadget" price: 24.99 }
{ name: "Gizmo" price: 49.99 }
{ name: "Doohickey" price: 4.99 }
]
expensive: products
filter(.price > 20)
map(.name str.to-upper)
eu products.eu -e expensive
Output:
- GADGET
- GIZMO
4. Generating Configuration with Shared Defaults
Problem: Generate environment-specific configs that share common defaults.
# config.eu
base: {
app: "my-service"
port: 8080
log-level: "info"
db: { host: "localhost" port: 5432 }
}
production: base << {
log-level: "warn"
db: { host: "prod-db.internal" }
}
staging: base << {
db: { host: "staging-db.internal" }
}
eu config.eu -e production -j
Output:
{
"app": "my-service",
"port": 8080,
"log-level": "warn",
"db": {
"host": "prod-db.internal",
"port": 5432
}
}
The << operator deep-merges blocks, so nested keys like db.port
are preserved while db.host is overridden.
5. CSV to JSON Conversion
Problem: Read a CSV file and output as a JSON array.
Given people.csv:
name,age,city
Alice,30,London
Bob,25,Manchester
Charlie,35,Edinburgh
eu rows=people.csv -j -e 'rows map(.name)'
Output:
["Alice", "Bob", "Charlie"]
Or to transform the data:
eu rows=people.csv -j -e 'rows map{ name: •0.name age: •0.age num }'
This converts age from string to number (CSV values are always strings).
6. Generating Availability Zone Names
Problem: Generate AWS availability zone names from a list of zone letters.
eu -e '["a", "b", "c"] map("eu-west-2{}")'
Output:
- eu-west-2a
- eu-west-2b
- eu-west-2c
The string "eu-west-2{}" is a function: {} is a string anaphor
that takes one argument.
7. Merging Multiple YAML Files
Problem: Combine values from several YAML files into a single output.
Given defaults.yaml:
timeout: 30
retries: 3
Given overrides.yaml:
timeout: 60
debug: true
eu defaults.yaml overrides.yaml
Output:
timeout: 60
retries: 3
debug: true
Later inputs override earlier ones. For a merged view with both available, use named inputs:
eu d=defaults.yaml o=overrides.yaml -e 'd << o'
8. Data Aggregation Pipeline
Problem: Compute summary statistics from structured data.
# sales.eu
sales: [
{ region: "North" amount: 1200 },
{ region: "South" amount: 800 },
{ region: "North" amount: 600 },
{ region: "South" amount: 1500 },
{ region: "East" amount: 900 }
]
` :suppress
amounts: sales map(.amount)
n: sales count
summary: {
total: amounts sum
count: n
average: (amounts sum) / n
max: amounts max-of
min: amounts min-of
}
eu sales.eu -e summary
Output:
total: 5000
count: 5
average: 1000
max: 1500
min: 600
9. Querying Deeply Nested Configuration
Problem: Find all port numbers in a complex configuration.
eu -e '{
web: { host: "0.0.0.0" port: 80 }
api: { host: "0.0.0.0" port: 8080 }
db: { host: "localhost" port: 5432 }
cache: { host: "localhost" port: 6379 }
} deep-query("port")'
Output:
- 80
- 8080
- 5432
- 6379
deep-query recursively searches nested blocks. You can also use
wildcards: deep-query("*.port", data) matches ports one level deep,
while deep-query("**.port", data) matches at any depth.
10. String Processing: Parsing Log Lines
Problem: Extract timestamps and levels from log lines.
# logs.eu
lines: [
"2024-03-15 10:30:00 ERROR Connection timeout"
"2024-03-15 10:30:05 INFO Retry attempt 1"
"2024-03-15 10:30:10 ERROR Connection timeout"
"2024-03-15 10:30:15 INFO Connected"
]
` :suppress
parse(line): line str.match-with("(\S+ \S+) (\w+) (.*)") tail
parsed: lines map(parse) map({parts: •}.({
timestamp: parts first
level: parts second
message: parts nth(2)
}))
errors: parsed filter(.level = "ERROR")
eu logs.eu -e errors
Output:
- timestamp: '2024-03-15 10:30:00'
level: ERROR
message: Connection timeout
- timestamp: '2024-03-15 10:30:10'
level: ERROR
message: Connection timeout
11. Templating CloudFormation Resources
Problem: Generate YAML with custom tags for CloudFormation.
# cfn.eu
resource(type, props): {
Type: type
Properties: props
}
resources: {
MyBucket: resource("AWS::S3::Bucket", {
BucketName: "my-bucket"
})
MyQueue: resource("AWS::SQS::Queue", {
QueueName: "my-queue"
})
}
This example shows how a simple function can template repetitive structure.
12. Working with Dates
Problem: Filter events by date and format the output.
# events.eu
events: [
{ name: "Launch" date: t"2024-01-15" }
{ name: "Review" date: t"2024-06-01" }
{ name: "Release" date: t"2024-09-30" }
]
cutoff: t"2024-06-01"
upcoming: events
filter(.date >= cutoff)
map(.name)
eu events.eu -e upcoming
Output:
- Review
- Release
The t"..." syntax creates date-time literals that support
comparison operators.
13. Generating a Lookup Table
Problem: Build a key-value mapping from two parallel lists.
eu -e '["Alice", 30, "London"] zip-kv[:name, :age, :city]'
Output:
name: Alice
age: 30
city: London
zip-kv pairs up symbols as keys with values to produce a block.
Note that zip-kv[:name, :age, :city] is shorthand for
zip-kv([:name, :age, :city]) — when a function takes a single list
or block argument, the outer parentheses can be omitted.
14. Parameterised Scripts
Problem: Write a reusable script that accepts command-line arguments.
# greet.eu
name: io.args head-or("World")
times: io.args tail head-or("1") num
greetings: repeat("Hello, {name}!") take(times)
eu greet.eu -e greetings -- Alice 3
Output:
- Hello, Alice!
- Hello, Alice!
- Hello, Alice!
Arguments after -- are available via io.args as a list of
strings. Use num to convert to numbers.
15. Set Operations: Finding Unique Values
Problem: Find the unique tags across multiple items and compute overlaps.
items: [
{ name: "A" tags: ["fast", "reliable", "cheap"] }
{ name: "B" tags: ["fast", "expensive"] }
{ name: "C" tags: ["reliable", "cheap", "slow"] }
]
` :suppress
tag-sets: items map(.tags set.from-list)
all-tags: tag-sets foldl(set.union, ∅) set.to-list
common-tags: tag-sets foldl(set.intersect, tag-sets head) set.to-list
result: {
all: all-tags
common: common-tags
}
eu tags.eu -e result
Output:
all:
- cheap
- expensive
- fast
- reliable
- slow
common: []
Next Steps
- Work through The Eucalypt Guide for a progressive tutorial
- Browse the Prelude Reference for the full standard library
- See the CLI Reference for all command-line options