lamess / yq命令文档摘录

Created Thu, 27 Mar 2025 09:35:52 +0800 Modified Thu, 27 Mar 2025 09:51:38 +0800
25083 Words

yq

a lightweight and portable command-line YAML processor written in go.

COMMANDS

Evaluate

Note that (as of 4.18.1) this is the default command when none is supplied to yq.

Usage:

yq eval [expression] [yaml_file1]... [flags]

Aliases: eval, e

Note that you can pass in - as a filename to pipe from STDIN.

Examples:

# runs the expression against each file, in series
yq '.a.b | length' f1.yml f2.yml 

# '-' will pipe from STDIN
cat file.yml | yq '.a.b' f1.yml -  f2.yml

# prints out the file
yq sample.yaml 
cat sample.yml | yq e

# prints a new yaml document
yq -n '.a.b.c = "cat"' 

# updates file.yaml directly
yq '.a.b = "cool"' -i file.yaml 

Flags:

  -h, --help          help for eval
  -C, --colors        force print with colors
  -e, --exit-status   set exit status if there are no matches or null or false is returned
  -I, --indent int    sets indent level for output (default 2)
  -i, --inplace       update the yaml file inplace of first yaml file given.
  -M, --no-colors     force print with no colors
  -N, --no-doc        Don't print document separators (---)
  -n, --null-input    Don't read input, simply evaluate the expression given. Useful for creating yaml docs from scratch.
  -j, --tojson        output as json. Set indent to 0 to print json in one line.
  -v, --verbose       verbose mode

Evaluate All

Evaluate All is most useful when needing to run expressions that depend on multiple yaml documents or files. Merge is probably the most common reason why evaluate all would be used. Note that eval-all consumes more memory than evaluate.

Like evaluate you can use - to pipe from STDIN.

Usage

yq eval-all [expression] [yaml_file1]... [flags]

Aliases: eval-all, ea

Examples

# merges f2.yml into f1.yml (inplace)
yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' f1.yml f2.yml

# you can merge into a file, piping from STDIN
cat somefile.yml | yq eval-all --inplace 'select(fileIndex == 0) * select(fileIndex == 1)' f1.yml -

Flags

  -h, --help          help for eval-all
  -C, --colors        force print with colors
  -e, --exit-status   set exit status if there are no matches or null or false is returned
  -I, --indent int    sets indent level for output (default 2)
  -i, --inplace       update the yaml file inplace of first yaml file given.
  -M, --no-colors     force print with no colors
  -N, --no-doc        Don't print document separators (---)
  -n, --null-input    Don't read input, simply evaluate the expression given. Useful for creating yaml docs from scratch.
  -j, --tojson        output as json. Set indent to 0 to print json in one line.
  -v, --verbose       verbose mode

OPERATORS

Add

Add behaves differently according to the type of the LHS:

  • arrays: concatenate
  • number scalars: arithmetic addition
  • string scalars: concatenate
  • maps: shallow merge (use the multiply operator (*) to deeply merge)

Use += as a relative append assign for things like increment. Note that .a += .x is equivalent to running .a = .a + .x.

Concatenate arrays

Given a sample.yml file of:

a:
  - 1
  - 2
b:
  - 3
  - 4

then

yq '.a + .b' sample.yml

will output

- 1
- 2
- 3
- 4

Concatenate to existing array

Note that the styling of a is kept.

Given a sample.yml file of:

a: [1,2]
b:
  - 3
  - 4

then

yq '.a += .b' sample.yml

will output

a: [1, 2, 3, 4]
b:
  - 3
  - 4

Concatenate null to array

Given a sample.yml file of:

a:
  - 1
  - 2

then

yq '.a + null' sample.yml

will output

- 1
- 2

Append to existing array

Note that the styling is copied from existing array elements

Given a sample.yml file of:

a: ['dog']

then

yq '.a += "cat"' sample.yml

will output

a: ['dog', 'cat']

Prepend to existing array

Given a sample.yml file of:

a:
  - dog

then

yq '.a = ["cat"] + .a' sample.yml

will output

a:
  - cat
  - dog

Add new object to array

Given a sample.yml file of:

a:
  - dog: woof

then

yq '.a + {"cat": "meow"}' sample.yml

will output

- dog: woof
- cat: meow

Relative append

Given a sample.yml file of:

a:
  a1:
    b:
      - cat
  a2:
    b:
      - dog
  a3: {}

then

yq '.a[].b += ["mouse"]' sample.yml

will output

a:
  a1:
    b:
      - cat
      - mouse
  a2:
    b:
      - dog
      - mouse
  a3:
    b:
      - mouse

String concatenation

Given a sample.yml file of:

a: cat
b: meow

then

yq '.a += .b' sample.yml

will output

a: catmeow
b: meow

Number addition - float

If the lhs or rhs are floats then the expression will be calculated with floats.

Given a sample.yml file of:

a: 3
b: 4.9

then

yq '.a = .a + .b' sample.yml

will output

a: 7.9
b: 4.9

Number addition - int

If both the lhs and rhs are ints then the expression will be calculated with ints.

Given a sample.yml file of:

a: 3
b: 4

then

yq '.a = .a + .b' sample.yml

will output

a: 7
b: 4

Increment numbers

Given a sample.yml file of:

a: 3
b: 5

then

yq '.[] += 1' sample.yml

will output

a: 4
b: 6

Date addition

You can add durations to dates. Assumes RFC3339 date time format, see date-time operators for more information.

Given a sample.yml file of:

a: 2021-01-01T00:00:00Z

then

yq '.a += "3h10m"' sample.yml

will output

a: 2021-01-01T03:10:00Z

Date addition - custom format

You can add durations to dates. See date-time operators for more information.

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM GMT

then

yq 'with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")' sample.yml

will output

a: Saturday, 15-Dec-01 at 6:00AM GMT

Add to null

Adding to null simply returns the rhs

Running

yq --null-input 'null + "cat"'

will output

cat

Add maps to shallow merge

Adding objects together shallow merges them. Use * to deeply merge.

Given a sample.yml file of:

a:
  thing:
    name: Astuff
    value: x
  a1: cool
b:
  thing:
    name: Bstuff
    legs: 3
  b1: neat

then

yq '.a += .b' sample.yml

will output

a:
  thing:
    name: Bstuff
    legs: 3
  a1: cool
  b1: neat
b:
  thing:
    name: Bstuff
    legs: 3
  b1: neat

Custom types: that are really strings

When custom tags are encountered, yq will try to decode the underlying type.

Given a sample.yml file of:

a: !horse cat
b: !goat _meow

then

yq '.a += .b' sample.yml

will output

a: !horse cat_meow
b: !goat _meow

Custom types: that are really numbers

When custom tags are encountered, yq will try to decode the underlying type.

Given a sample.yml file of:

a: !horse 1.2
b: !goat 2.3

then

yq '.a += .b' sample.yml

will output

a: !horse 3.5
b: !goat 2.3

Alternative (Default value)

This operator is used to provide alternative (or default) values when a particular expression is either null or false.

LHS is defined

Given a sample.yml file of:

a: bridge

then

yq '.a // "hello"' sample.yml

will output

bridge

LHS is not defined

Given a sample.yml file of:

{}

then

yq '.a // "hello"' sample.yml

will output

hello

LHS is null

Given a sample.yml file of:

a: ~

then

yq '.a // "hello"' sample.yml

will output

hello

LHS is false

Given a sample.yml file of:

a: false

then

yq '.a // "hello"' sample.yml

will output

hello

RHS is an expression

Given a sample.yml file of:

a: false
b: cat

then

yq '.a // .b' sample.yml

will output

cat

Update or create - entity exists

This initialises a if it’s not present

Given a sample.yml file of:

a: 1

then

yq '(.a // (.a = 0)) += 1' sample.yml

will output

a: 2

Update or create - entity does not exist

This initialises a if it’s not present

Given a sample.yml file of:

b: camel

then

yq '(.a // (.a = 0)) += 1' sample.yml

will output

b: camel
a: 1

Anchor and Alias Operators

Use the alias and anchor operators to read and write yaml aliases and anchors. The explode operator normalises a yaml file (dereference (or expands) aliases and remove anchor names).

yq supports merge aliases (like <<: *blah) however this is no longer in the standard yaml spec (1.2) and so yq will automatically add the !!merge tag to these nodes as it is effectively a custom tag.

Merge one map

see https://yaml.org/type/merge.html

Given a sample.yml file of:

- &CENTER
  x: 1
  y: 2
- &LEFT
  x: 0
  y: 2
- &BIG
  r: 10
- &SMALL
  r: 1
- !!merge <<: *CENTER
  r: 10

then

yq '.[4] | explode(.)' sample.yml

will output

x: 1
y: 2
r: 10

Merge multiple maps

see https://yaml.org/type/merge.html

Given a sample.yml file of:

- &CENTER
  x: 1
  y: 2
- &LEFT
  x: 0
  y: 2
- &BIG
  r: 10
- &SMALL
  r: 1
- !!merge <<:
    - *CENTER
    - *BIG

then

yq '.[4] | explode(.)' sample.yml

will output

r: 10
x: 1
y: 2

Override

see https://yaml.org/type/merge.html

Given a sample.yml file of:

- &CENTER
  x: 1
  y: 2
- &LEFT
  x: 0
  y: 2
- &BIG
  r: 10
- &SMALL
  r: 1
- !!merge <<:
    - *BIG
    - *LEFT
    - *SMALL
  x: 1

then

yq '.[4] | explode(.)' sample.yml

will output

r: 10
x: 1
y: 2

Get anchor

Given a sample.yml file of:

a: &billyBob cat

then

yq '.a | anchor' sample.yml

will output

billyBob

Set anchor

Given a sample.yml file of:

a: cat

then

yq '.a anchor = "foobar"' sample.yml

will output

a: &foobar cat

Set anchor relatively using assign-update

Given a sample.yml file of:

a:
  b: cat

then

yq '.a anchor |= .b' sample.yml

will output

a: &cat
  b: cat

Get alias

Given a sample.yml file of:

b: &billyBob meow
a: *billyBob

then

yq '.a | alias' sample.yml

will output

billyBob

Set alias

Given a sample.yml file of:

b: &meow purr
a: cat

then

yq '.a alias = "meow"' sample.yml

will output

b: &meow purr
a: *meow

Set alias to blank does nothing

Given a sample.yml file of:

b: &meow purr
a: cat

then

yq '.a alias = ""' sample.yml

will output

b: &meow purr
a: cat

Set alias relatively using assign-update

Given a sample.yml file of:

b: &meow purr
a:
  f: meow

then

yq '.a alias |= .f' sample.yml

will output

b: &meow purr
a: *meow

Explode alias and anchor

Given a sample.yml file of:

f:
  a: &a cat
  b: *a

then

yq 'explode(.f)' sample.yml

will output

f:
  a: cat
  b: cat

Explode with no aliases or anchors

Given a sample.yml file of:

a: mike

then

yq 'explode(.a)' sample.yml

will output

a: mike

Explode with alias keys

Given a sample.yml file of:

f:
  a: &a cat
  *a: b

then

yq 'explode(.f)' sample.yml

will output

f:
  a: cat
  cat: b

Explode with merge anchors

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq 'explode(.)' sample.yml

will output

foo:
  a: foo_a
  thing: foo_thing
  c: foo_c
bar:
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: bar_b
  thing: foo_thing
  c: foobarList_c
  a: foo_a
foobar:
  c: foo_c
  a: foo_a
  thing: foobar_thing

Dereference and update a field

Use explode with multiply to dereference an object

Given a sample.yml file of:

item_value: &item_value
  value: true
thingOne:
  name: item_1
  !!merge <<: *item_value
thingTwo:
  name: item_2
  !!merge <<: *item_value

then

yq '.thingOne |= explode(.) * {"value": false}' sample.yml

will output

item_value: &item_value
  value: true
thingOne:
  name: item_1
  value: false
thingTwo:
  name: item_2
  !!merge <<: *item_value

Array to Map

Use this operator to convert an array to..a map. The indices are used as map keys, null values in the array are skipped over.

Behind the scenes, this is implemented using reduce:

(.[] | select(. != null) ) as $i ireduce({}; .[$i | key] = $i)

Simple example

Given a sample.yml file of:

cool:
  - null
  - null
  - hello

then

yq '.cool |= array_to_map' sample.yml

will output

cool:
  2: hello

Assign (Update)

This operator is used to update node values. It can be used in either the:

plain form: =

Which will set the LHS node values equal to the RHS node values. The RHS expression is run against the matching nodes in the pipeline.

relative form: |=

This will do a similar thing to the plain form, but the RHS expression is run with each LHS node as context. This is useful for updating values based on old values, e.g. increment.

Flags
  • c clobber custom tags

Create yaml file

Running

yq --null-input '.a.b = "cat" | .x = "frog"'

will output

a:
  b: cat
x: frog

Update node to be the child value

Given a sample.yml file of:

a:
  b:
    g: foof

then

yq '.a |= .b' sample.yml

will output

a:
  g: foof

Double elements in an array

Given a sample.yml file of:

- 1
- 2
- 3

then

yq '.[] |= . * 2' sample.yml

will output

- 2
- 4
- 6

Update node from another file

Note this will also work when the second file is a scalar (string/number)

Given a sample.yml file of:

a: apples

And another sample another.yml file of:

b: bob

then

yq eval-all 'select(fileIndex==0).a = select(fileIndex==1) | select(fileIndex==0)' sample.yml another.yml

will output

a:
  b: bob

Update node to be the sibling value

Given a sample.yml file of:

a:
  b: child
b: sibling

then

yq '.a = .b' sample.yml

will output

a: sibling
b: sibling

Updated multiple paths

Given a sample.yml file of:

a: fieldA
b: fieldB
c: fieldC

then

yq '(.a, .c) = "potato"' sample.yml

will output

a: potato
b: fieldB
c: potato

Update string value

Given a sample.yml file of:

a:
  b: apple

then

yq '.a.b = "frog"' sample.yml

will output

a:
  b: frog

Update string value via |=

Note there is no difference between = and |= when the RHS is a scalar

Given a sample.yml file of:

a:
  b: apple

then

yq '.a.b |= "frog"' sample.yml

will output

a:
  b: frog

Update deeply selected results

Note that the LHS is wrapped in brackets! This is to ensure we don’t first filter out the yaml and then update the snippet.

Given a sample.yml file of:

a:
  b: apple
  c: cactus

then

yq '(.a[] | select(. == "apple")) = "frog"' sample.yml

will output

a:
  b: frog
  c: cactus

Update array values

Given a sample.yml file of:

- candy
- apple
- sandy

then

yq '(.[] | select(. == "*andy")) = "bogs"' sample.yml

will output

- bogs
- apple
- bogs

Update empty object

Given a sample.yml file of:

{}

then

yq '.a.b |= "bogs"' sample.yml

will output

a:
  b: bogs

Update node value that has an anchor

Anchor will remain

Given a sample.yml file of:

a: &cool cat

then

yq '.a = "dog"' sample.yml

will output

a: &cool dog

Update empty object and array

Given a sample.yml file of:

{}

then

yq '.a.b.[0] |= "bogs"' sample.yml

will output

a:
  b:
    - bogs

Custom types are maintained by default

Given a sample.yml file of:

a: !cat meow
b: !dog woof

then

yq '.a = .b' sample.yml

will output

a: !cat woof
b: !dog woof

Custom types: clobber

Use the c option to clobber custom tags

Given a sample.yml file of:

a: !cat meow
b: !dog woof

then

yq '.a =c .b' sample.yml

will output

a: !dog woof
b: !dog woof

Boolean Operators

The or and and operators take two parameters and return a boolean result.

not flips a boolean from true to false, or vice versa.

any will return true if there are any true values in an array sequence, and all will return true if all elements in an array are true.

any_c(condition) and all_c(condition) are like any and all but they take a condition expression that is used against each element to determine if it’s true. Note: in jq you can simply pass a condition to any or all and it simply works - yq isn’t that clever..yet

These are most commonly used with the select operator to filter particular nodes.

  • equals / not equals (==, !=) operators here
  • comparison (>=, < etc) operators here
  • select operator here

or example

Running

yq --null-input 'true or false'

will output

true

“yes” and “no” are strings

In the yaml 1.2 standard, support for yes/no as booleans was dropped - they are now considered strings. See ‘10.2.1.2. Boolean’ in https://yaml.org/spec/1.2.2/

Given a sample.yml file of:

- yes
- no

then

yq '.[] | tag' sample.yml

will output

!!str
!!str

and example

Running

yq --null-input 'true and false'

will output

false

Matching nodes with select, equals and or

Given a sample.yml file of:

- a: bird
  b: dog
- a: frog
  b: bird
- a: cat
  b: fly

then

yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml

will output

- a: bird
  b: dog
- a: cat
  b: fly

any returns true if any boolean in a given array is true

Given a sample.yml file of:

- false
- true

then

yq 'any' sample.yml

will output

true

any returns false for an empty array

Given a sample.yml file of:

[]

then

yq 'any' sample.yml

will output

false

any_c returns true if any element in the array is true for the given condition.

Given a sample.yml file of:

a:
  - rad
  - awesome
b:
  - meh
  - whatever

then

yq '.[] |= any_c(. == "awesome")' sample.yml

will output

a: true
b: false

all returns true if all booleans in a given array are true

Given a sample.yml file of:

- true
- true

then

yq 'all' sample.yml

will output

true

all returns true for an empty array

Given a sample.yml file of:

[]

then

yq 'all' sample.yml

will output

true

all_c returns true if all elements in the array are true for the given condition.

Given a sample.yml file of:

a:
  - rad
  - awesome
b:
  - meh
  - 12

then

yq '.[] |= all_c(tag == "!!str")' sample.yml

will output

a: true
b: false

Not true is false

Running

yq --null-input 'true | not'

will output

false

Not false is true

Running

yq --null-input 'false | not'

will output

true

String values considered to be true

Running

yq --null-input '"cat" | not'

will output

false

Empty string value considered to be true

Running

yq --null-input '"" | not'

will output

false

Numbers are considered to be true

Running

yq --null-input '1 | not'

will output

false

Zero is considered to be true

Running

yq --null-input '0 | not'

will output

false

Null is considered to be false

Running

yq --null-input '~ | not'

will output

true

Collect into Array

This creates an array using the expression between the square brackets.

Collect empty

Running

yq --null-input '[]'

will output

[]

Collect single

Running

yq --null-input '["cat"]'

will output

- cat

Collect many

Given a sample.yml file of:

a: cat
b: dog

then

yq '[.a, .b]' sample.yml

will output

- cat
- dog

Column

Returns the column of the matching node. Starts from 1, 0 indicates there was no column data.

Column is the number of characters that precede that node on the line it starts.

Returns column of value node

Given a sample.yml file of:

a: cat
b: bob

then

yq '.b | column' sample.yml

will output

4

Returns column of key node

Pipe through the key operator to get the column of the key

Given a sample.yml file of:

a: cat
b: bob

then

yq '.b | key | column' sample.yml

will output

1

First column is 1

Given a sample.yml file of:

a: cat

then

yq '.a | key | column' sample.yml

will output

1

No column data is 0

Running

yq --null-input '{"a": "new entry"} | column'

will output

0

Comment Operators

Use these comment operators to set or retrieve comments. Note that line comments on maps/arrays are actually set on the key node as opposed to the value (map/array). See below for examples.

Like the = and |= assign operators, the same syntax applies when updating comments:

plain form: =

This will set the LHS nodes’ comments equal to the expression on the RHS. The RHS is run against the matching nodes in the pipeline

relative form: |=

This is similar to the plain form, but it evaluates the RHS with each matching LHS node as context. This is useful if you want to set the comments as a relative expression of the node, for instance its value or path.

Set line comment

Set the comment on the key node for more reliability (see below).

Given a sample.yml file of:

a: cat

then

yq '.a line_comment="single"' sample.yml

will output

a: cat # single

Set line comment of a maps/arrays

For maps and arrays, you need to set the line comment on the key node. This will also work for scalars.

Given a sample.yml file of:

a:
  b: things

then

yq '(.a | key) line_comment="single"' sample.yml

will output

a: # single
  b: things

Use update assign to perform relative updates

Given a sample.yml file of:

a: cat
b: dog

then

yq '.. line_comment |= .' sample.yml

will output

a: cat # cat
b: dog # dog

Where is the comment - map key example

The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. ‘p’ indicates the path, ‘isKey’ is if the node is a map key (as opposed to a map value). From this, you can see the ‘hello-world-comment’ is actually on the ‘hello’ key

Given a sample.yml file of:

hello: # hello-world-comment
  message: world

then

yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml

will output

- p: ""
  isKey: false
  hc: ""
  lc: ""
  fc: ""
- p: hello
  isKey: true
  hc: ""
  lc: hello-world-comment
  fc: ""
- p: hello
  isKey: false
  hc: ""
  lc: ""
  fc: ""
- p: hello.message
  isKey: true
  hc: ""
  lc: ""
  fc: ""
- p: hello.message
  isKey: false
  hc: ""
  lc: ""
  fc: ""

Retrieve comment - map key example

From the previous example, we know that the comment is on the ‘hello’ key as a lineComment

Given a sample.yml file of:

hello: # hello-world-comment
  message: world

then

yq '.hello | key | line_comment' sample.yml

will output

hello-world-comment

Where is the comment - array example

The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. ‘p’ indicates the path, ‘isKey’ is if the node is a map key (as opposed to a map value). From this, you can see the ‘under-name-comment’ is actually on the first child

Given a sample.yml file of:

name:
  # under-name-comment
  - first-array-child

then

yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml

will output

- p: ""
  isKey: false
  hc: ""
  lc: ""
  fc: ""
- p: name
  isKey: true
  hc: ""
  lc: ""
  fc: ""
- p: name
  isKey: false
  hc: ""
  lc: ""
  fc: ""
- p: name.0
  isKey: false
  hc: under-name-comment
  lc: ""
  fc: ""

Retrieve comment - array example

From the previous example, we know that the comment is on the first child as a headComment

Given a sample.yml file of:

name:
  # under-name-comment
  - first-array-child

then

yq '.name[0] | headComment' sample.yml

will output

under-name-comment

Set head comment

Given a sample.yml file of:

a: cat

then

yq '. head_comment="single"' sample.yml

will output

# single
a: cat

Set head comment of a map entry

Given a sample.yml file of:

f: foo
a:
  b: cat

then

yq '(.a | key) head_comment="single"' sample.yml

will output

f: foo
# single
a:
  b: cat

Set foot comment, using an expression

Given a sample.yml file of:

a: cat

then

yq '. foot_comment=.a' sample.yml

will output

a: cat
# cat

Remove comment

Given a sample.yml file of:

a: cat # comment
b: dog # leave this

then

yq '.a line_comment=""' sample.yml

will output

a: cat
b: dog # leave this

Remove (strip) all comments

Note the use of ... to ensure key nodes are included.

Given a sample.yml file of:

# hi

a: cat # comment
# great
b: # key comment

then

yq '... comments=""' sample.yml

will output

a: cat
b:

Get line comment

Given a sample.yml file of:

# welcome!

a: cat # meow
# have a great day

then

yq '.a | line_comment' sample.yml

will output

meow

Get head comment

Given a sample.yml file of:

# welcome!

a: cat # meow

# have a great day

then

yq '. | head_comment' sample.yml

will output

welcome!

Head comment with document split

Given a sample.yml file of:

# welcome!
---
# bob
a: cat # meow

# have a great day

then

yq 'head_comment' sample.yml

will output

welcome!
bob

Get foot comment

Given a sample.yml file of:

# welcome!

a: cat # meow

# have a great day
# no really

then

yq '. | foot_comment' sample.yml

will output

have a great day
no really

Compare Operators

Comparison operators (>, >=, <, <=) can be used for comparing scalar values of the same time.

The following types are currently supported:

  • numbers
  • strings
  • datetimes
  • equals / not equals (==, !=) operators here
  • boolean operators (and, or, any etc) here
  • select operator here

Compare numbers (>)

Given a sample.yml file of:

a: 5
b: 4

then

yq '.a > .b' sample.yml

will output

true

Compare equal numbers (>=)

Given a sample.yml file of:

a: 5
b: 5

then

yq '.a >= .b' sample.yml

will output

true

Compare strings

Compares strings by their bytecode.

Given a sample.yml file of:

a: zoo
b: apple

then

yq '.a > .b' sample.yml

will output

true

Compare date times

You can compare date times. Assumes RFC3339 date time format, see date-time operators for more information.

Given a sample.yml file of:

a: 2021-01-01T03:10:00Z
b: 2020-01-01T03:10:00Z

then

yq '.a > .b' sample.yml

will output

true

Both sides are null: > is false

Running

yq --null-input '.a > .b'

will output

false

Both sides are null: >= is true

Running

yq --null-input '.a >= .b'

will output

true

Contains

This returns true if the context contains the passed in parameter, and false otherwise. For arrays, this will return true if the passed in array is contained within the array. For strings, it will return true if the string is a substring.

{% hint style=“warning” %}

Note that, just like jq, when checking if an array of strings contains another, this will use contains and not equals to check each string. This means an expression like contains(["cat"]) will return true for an array ["cats"].

See the “Array has a subset array” example below on how to check for a subset.

{% endhint %}

Array contains array

Array is equal or subset of

Given a sample.yml file of:

- foobar
- foobaz
- blarp

then

yq 'contains(["baz", "bar"])' sample.yml

will output

true

Array has a subset array

Subtract the superset array from the subset, if there’s anything left, it’s not a subset

Given a sample.yml file of:

- foobar
- foobaz
- blarp

then

yq '["baz", "bar"] - . | length == 0' sample.yml

will output

false

Object included in array

Given a sample.yml file of:

"foo": 12
"bar":
  - 1
  - 2
  - "barp": 12
    "blip": 13

then

yq 'contains({"bar": [{"barp": 12}]})' sample.yml

will output

true

Object not included in array

Given a sample.yml file of:

"foo": 12
"bar":
  - 1
  - 2
  - "barp": 12
    "blip": 13

then

yq 'contains({"foo": 12, "bar": [{"barp": 15}]})' sample.yml

will output

false

String contains substring

Given a sample.yml file of:

foobar

then

yq 'contains("bar")' sample.yml

will output

true

String equals string

Given a sample.yml file of:

meow

then

yq 'contains("meow")' sample.yml

will output

true

Create, Collect into Object

This is used to construct objects (or maps). This can be used against existing yaml, or to create fresh yaml documents.

Collect empty object

Running

yq --null-input '{}'

will output

{}

Wrap (prefix) existing object

Given a sample.yml file of:

name: Mike

then

yq '{"wrap": .}' sample.yml

will output

wrap:
  name: Mike

Using splat to create multiple objects

Given a sample.yml file of:

name: Mike
pets:
  - cat
  - dog

then

yq '{.name: .pets.[]}' sample.yml

will output

Mike: cat
Mike: dog

Working with multiple documents

Given a sample.yml file of:

name: Mike
pets:
  - cat
  - dog
---
name: Rosey
pets:
  - monkey
  - sheep

then

yq '{.name: .pets.[]}' sample.yml

will output

Mike: cat
Mike: dog
---
Rosey: monkey
Rosey: sheep

Creating yaml from scratch

Running

yq --null-input '{"wrap": "frog"}'

will output

wrap: frog

Creating yaml from scratch with multiple objects

Running

yq --null-input '(.a.b = "foo") | (.d.e = "bar")'

will output

a:
  b: foo
d:
  e: bar

Date Time

Various operators for parsing and manipulating dates.

Date time formattings

This uses Golang’s built in time library for parsing and formatting date times.

When not specified, the RFC3339 standard is assumed 2006-01-02T15:04:05Z07:00 for parsing.

To specify a custom parsing format, use the with_dtf operator. The first parameter sets the datetime parsing format for the expression in the second parameter. The expression can be any valid yq expression tree.

yq 'with_dtf("myformat"; .a + "3h" | tz("Australia/Melbourne"))'

See the library docs for examples of formatting options.

Timezones

This uses Golang’s built in LoadLocation function to parse timezones strings. See the library docs for more details.

Durations

Durations are parsed using Golang’s built in ParseDuration function.

You can add durations to time using the + operator.

Format: from standard RFC3339 format

Providing a single parameter assumes a standard RFC3339 datetime format. If the target format is not a valid yaml datetime format, the result will be a string tagged node.

Given a sample.yml file of:

a: 2001-12-15T02:59:43.1Z

then

yq '.a |= format_datetime("Monday, 02-Jan-06 at 3:04PM")' sample.yml

will output

a: Saturday, 15-Dec-01 at 2:59AM

Format: from custom date time

Use with_dtf to set a custom datetime format for parsing.

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM

then

yq '.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM"; format_datetime("2006-01-02"))' sample.yml

will output

a: 2001-12-15

Format: get the day of the week

Given a sample.yml file of:

a: 2001-12-15

then

yq '.a | format_datetime("Monday")' sample.yml

will output

Saturday

Now

Given a sample.yml file of:

a: cool

then

yq '.updated = now' sample.yml

will output

a: cool
updated: 2021-05-19T01:02:03Z

From Unix

Converts from unix time. Note, you don’t have to pipe through the tz operator :)

Running

yq --null-input '1675301929 | from_unix | tz("UTC")'

will output

2023-02-02T01:38:49Z

To Unix

Converts to unix time

Running

yq --null-input 'now | to_unix'

will output

1621386123

Timezone: from standard RFC3339 format

Returns a new datetime in the specified timezone. Specify standard IANA Time Zone format or ‘utc’, ’local’. When given a single parameter, this assumes the datetime is in RFC3339 format.

Given a sample.yml file of:

a: cool

then

yq '.updated = (now | tz("Australia/Sydney"))' sample.yml

will output

a: cool
updated: 2021-05-19T11:02:03+10:00

Timezone: with custom format

Specify standard IANA Time Zone format or ‘utc’, ’local’

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM GMT

then

yq '.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; tz("Australia/Sydney"))' sample.yml

will output

a: Saturday, 15-Dec-01 at 1:59PM AEDT

Add and tz custom format

Specify standard IANA Time Zone format or ‘utc’, ’local’

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM GMT

then

yq '.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; tz("Australia/Sydney"))' sample.yml

will output

a: Saturday, 15-Dec-01 at 1:59PM AEDT

Date addition

Given a sample.yml file of:

a: 2021-01-01T00:00:00Z

then

yq '.a += "3h10m"' sample.yml

will output

a: 2021-01-01T03:10:00Z

Date subtraction

You can subtract durations from dates. Assumes RFC3339 date time format, see date-time operators for more information.

Given a sample.yml file of:

a: 2021-01-01T03:10:00Z

then

yq '.a -= "3h10m"' sample.yml

will output

a: 2021-01-01T00:00:00Z

Date addition - custom format

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM GMT

then

yq 'with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; .a += "3h1m")' sample.yml

will output

a: Saturday, 15-Dec-01 at 6:00AM GMT

Date script with custom format

You can embed full expressions in with_dtf if needed.

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 2:59AM GMT

then

yq 'with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; .a = (.a + "3h1m" | tz("Australia/Perth")))' sample.yml

will output

a: Saturday, 15-Dec-01 at 2:00PM AWST

Delete

Deletes matching entries in maps or arrays.

Delete entry in map

Given a sample.yml file of:

a: cat
b: dog

then

yq 'del(.b)' sample.yml

will output

a: cat

Delete nested entry in map

Given a sample.yml file of:

a:
  a1: fred
  a2: frood

then

yq 'del(.a.a1)' sample.yml

will output

a:
  a2: frood

Delete entry in array

Given a sample.yml file of:

- 1
- 2
- 3

then

yq 'del(.[1])' sample.yml

will output

- 1
- 3

Delete nested entry in array

Given a sample.yml file of:

- a: cat
  b: dog

then

yq 'del(.[0].a)' sample.yml

will output

- b: dog

Delete no matches

Given a sample.yml file of:

a: cat
b: dog

then

yq 'del(.c)' sample.yml

will output

a: cat
b: dog

Delete matching entries

Given a sample.yml file of:

a: cat
b: dog
c: bat

then

yq 'del( .[] | select(. == "*at") )' sample.yml

will output

b: dog

Recursively delete matching keys

Given a sample.yml file of:

a:
  name: frog
  b:
    name: blog
    age: 12

then

yq 'del(.. | select(has("name")).name)' sample.yml

will output

a:
  b:
    age: 12

Divide

Divide behaves differently according to the type of the LHS:

  • strings: split by the divider
  • number: arithmetic division

String split

Given a sample.yml file of:

a: cat_meow
b: _

then

yq '.c = .a / .b' sample.yml

will output

a: cat_meow
b: _
c:
  - cat
  - meow

Number division

The result during division is calculated as a float

Given a sample.yml file of:

a: 12
b: 2.5

then

yq '.a = .a / .b' sample.yml

will output

a: 4.8
b: 2.5

Number division by zero

Dividing by zero results in +Inf or -Inf

Given a sample.yml file of:

a: 1
b: -1

then

yq '.a = .a / 0 | .b = .b / 0' sample.yml

will output

a: !!float +Inf
b: !!float -Inf

Document Index

Use the documentIndex operator (or the di shorthand) to select nodes of a particular document.

Retrieve a document index

Given a sample.yml file of:

a: cat
---
a: frog

then

yq '.a | document_index' sample.yml

will output

0
---
1

Retrieve a document index, shorthand

Given a sample.yml file of:

a: cat
---
a: frog

then

yq '.a | di' sample.yml

will output

0
---
1

Filter by document index

Given a sample.yml file of:

a: cat
---
a: frog

then

yq 'select(document_index == 1)' sample.yml

will output

a: frog

Filter by document index shorthand

Given a sample.yml file of:

a: cat
---
a: frog

then

yq 'select(di == 1)' sample.yml

will output

a: frog

Given a sample.yml file of:

a: cat
---
a: frog

then

yq '.a | ({"match": ., "doc": document_index})' sample.yml

will output

match: cat
doc: 0
---
match: frog
doc: 1

Encode / Decode

Encode operators will take the piped in object structure and encode it as a string in the desired format. The decode operators do the opposite, they take a formatted string and decode it into the relevant object structure.

Note that you can optionally pass an indent value to the encode functions (see below).

These operators are useful to process yaml documents that have stringified embedded yaml/json/props in them.

Format Decode (from string) Encode (to string)
Yaml from_yaml/@yamld to_yaml(i)/@yaml
JSON from_json/@jsond to_json(i)/@json
Properties from_props/@propsd to_props/@props
CSV from_csv/@csvd to_csv/@csv
TSV from_tsv/@tsvd to_tsv/@tsv
XML from_xml/@xmld to_xml(i)/@xml
Base64 @base64d @base64
URI @urid @uri
Shell @sh

See CSV and TSV documentation for accepted formats.

XML uses the --xml-attribute-prefix and xml-content-name flags to identify attributes and content fields.

Base64 assumes rfc4648 encoding. Encoding and decoding both assume that the content is a utf-8 string and not binary content.

Encode value as json string

Given a sample.yml file of:

a:
  cool: thing

then

yq '.b = (.a | to_json)' sample.yml

will output

a:
  cool: thing
b: |
  {
    "cool": "thing"
  }  

Encode value as json string, on one line

Pass in a 0 indent to print json on a single line.

Given a sample.yml file of:

a:
  cool: thing

then

yq '.b = (.a | to_json(0))' sample.yml

will output

a:
  cool: thing
b: '{"cool":"thing"}'

Encode value as json string, on one line shorthand

Pass in a 0 indent to print json on a single line.

Given a sample.yml file of:

a:
  cool: thing

then

yq '.b = (.a | @json)' sample.yml

will output

a:
  cool: thing
b: '{"cool":"thing"}'

Decode a json encoded string

Keep in mind JSON is a subset of YAML. If you want idiomatic yaml, pipe through the style operator to clear out the JSON styling.

Given a sample.yml file of:

a: '{"cool":"thing"}'

then

yq '.a | from_json | ... style=""' sample.yml

will output

cool: thing

Encode value as props string

Given a sample.yml file of:

a:
  cool: thing

then

yq '.b = (.a | @props)' sample.yml

will output

a:
  cool: thing
b: |
  cool = thing  

Decode props encoded string

Given a sample.yml file of:

a: |-
  cats=great
  dogs=cool as well  

then

yq '.a |= @propsd' sample.yml

will output

a:
  cats: great
  dogs: cool as well

Decode csv encoded string

Given a sample.yml file of:

a: |-
  cats,dogs
  great,cool as well  

then

yq '.a |= @csvd' sample.yml

will output

a:
  - cats: great
    dogs: cool as well

Decode tsv encoded string

Given a sample.yml file of:

a: |-
  cats	dogs
  great	cool as well  

then

yq '.a |= @tsvd' sample.yml

will output

a:
  - cats: great
    dogs: cool as well

Encode value as yaml string

Indent defaults to 2

Given a sample.yml file of:

a:
  cool:
    bob: dylan

then

yq '.b = (.a | to_yaml)' sample.yml

will output

a:
  cool:
    bob: dylan
b: |
  cool:
    bob: dylan  

Encode value as yaml string, with custom indentation

You can specify the indentation level as the first parameter.

Given a sample.yml file of:

a:
  cool:
    bob: dylan

then

yq '.b = (.a | to_yaml(8))' sample.yml

will output

a:
  cool:
    bob: dylan
b: |
  cool:
          bob: dylan  

Decode a yaml encoded string

Given a sample.yml file of:

a: 'foo: bar'

then

yq '.b = (.a | from_yaml)' sample.yml

will output

a: 'foo: bar'
b:
  foo: bar

Update a multiline encoded yaml string

Given a sample.yml file of:

a: |
  foo: bar
  baz: dog  

then

yq '.a |= (from_yaml | .foo = "cat" | to_yaml)' sample.yml

will output

a: |
  foo: cat
  baz: dog  

Update a single line encoded yaml string

Given a sample.yml file of:

a: 'foo: bar'

then

yq '.a |= (from_yaml | .foo = "cat" | to_yaml)' sample.yml

will output

a: 'foo: cat'

Encode array of scalars as csv string

Scalars are strings, numbers and booleans.

Given a sample.yml file of:

- cat
- thing1,thing2
- true
- 3.40

then

yq '@csv' sample.yml

will output

cat,"thing1,thing2",true,3.40

Encode array of arrays as csv string

Given a sample.yml file of:

- - cat
  - thing1,thing2
  - true
  - 3.40
- - dog
  - thing3
  - false
  - 12

then

yq '@csv' sample.yml

will output

cat,"thing1,thing2",true,3.40
dog,thing3,false,12

Encode array of arrays as tsv string

Scalars are strings, numbers and booleans.

Given a sample.yml file of:

- - cat
  - thing1,thing2
  - true
  - 3.40
- - dog
  - thing3
  - false
  - 12

then

yq '@tsv' sample.yml

will output

cat	thing1,thing2	true	3.40
dog	thing3	false	12

Encode value as xml string

Given a sample.yml file of:

a:
  cool:
    foo: bar
    +@id: hi

then

yq '.a | to_xml' sample.yml

will output

<cool id="hi">
  <foo>bar</foo>
</cool>

Encode value as xml string on a single line

Given a sample.yml file of:

a:
  cool:
    foo: bar
    +@id: hi

then

yq '.a | @xml' sample.yml

will output

<cool id="hi"><foo>bar</foo></cool>

Encode value as xml string with custom indentation

Given a sample.yml file of:

a:
  cool:
    foo: bar
    +@id: hi

then

yq '{"cat": .a | to_xml(1)}' sample.yml

will output

cat: |
  <cool id="hi">
   <foo>bar</foo>
  </cool>  

Decode a xml encoded string

Given a sample.yml file of:

a: <foo>bar</foo>

then

yq '.b = (.a | from_xml)' sample.yml

will output

a: <foo>bar</foo>
b:
  foo: bar

Encode a string to base64

Given a sample.yml file of:

coolData: a special string

then

yq '.coolData | @base64' sample.yml

will output

YSBzcGVjaWFsIHN0cmluZw==

Encode a yaml document to base64

Pipe through @yaml first to convert to a string, then use @base64 to encode it.

Given a sample.yml file of:

a: apple

then

yq '@yaml | @base64' sample.yml

will output

YTogYXBwbGUK

Encode a string to uri

Given a sample.yml file of:

coolData: this has & special () characters *

then

yq '.coolData | @uri' sample.yml

will output

this+has+%26+special+%28%29+characters+%2A

Decode a URI to a string

Given a sample.yml file of:

this+has+%26+special+%28%29+characters+%2A

then

yq '@urid' sample.yml

will output

this has & special () characters *

Encode a string to sh

Sh/Bash friendly string

Given a sample.yml file of:

coolData: strings with spaces and a 'quote'

then

yq '.coolData | @sh' sample.yml

will output

strings' with spaces and a '\'quote\'

Decode a base64 encoded string

Decoded data is assumed to be a string.

Given a sample.yml file of:

coolData: V29ya3Mgd2l0aCBVVEYtMTYg8J+Yig==

then

yq '.coolData | @base64d' sample.yml

will output

Works with UTF-16 😊

Decode a base64 encoded yaml document

Pipe through from_yaml to parse the decoded base64 string as a yaml document.

Given a sample.yml file of:

coolData: YTogYXBwbGUK

then

yq '.coolData |= (@base64d | from_yaml)' sample.yml

will output

coolData:
  a: apple

Entries

Similar to the same named functions in jq these functions convert to/from an object and an array of key-value pairs. This is most useful for performing operations on keys of maps.

Use with_entries(op) as a syntatic sugar for doing to_entries | op | from_entries.

to_entries Map

Given a sample.yml file of:

a: 1
b: 2

then

yq 'to_entries' sample.yml

will output

- key: a
  value: 1
- key: b
  value: 2

to_entries Array

Given a sample.yml file of:

- a
- b

then

yq 'to_entries' sample.yml

will output

- key: 0
  value: a
- key: 1
  value: b

to_entries null

Given a sample.yml file of:

null

then

yq 'to_entries' sample.yml

will output

from_entries map

Given a sample.yml file of:

a: 1
b: 2

then

yq 'to_entries | from_entries' sample.yml

will output

a: 1
b: 2

from_entries with numeric key indices

from_entries always creates a map, even for numeric keys

Given a sample.yml file of:

- a
- b

then

yq 'to_entries | from_entries' sample.yml

will output

0: a
1: b

Use with_entries to update keys

Given a sample.yml file of:

a: 1
b: 2

then

yq 'with_entries(.key |= "KEY_" + .)' sample.yml

will output

KEY_a: 1
KEY_b: 2

Use with_entries to update keys recursively

We use (.. | select(tag=“map”)) to find all the maps in the doc, then |= to update each one of those maps. In the update, with_entries is used.

Given a sample.yml file of:

a: 1
b:
  b_a: nested
  b_b: thing

then

yq '(.. | select(tag=="!!map")) |= with_entries(.key |= "KEY_" + .)' sample.yml

will output

KEY_a: 1
KEY_b:
  KEY_b_a: nested
  KEY_b_b: thing

Custom sort map keys

Use to_entries to convert to an array of key/value pairs, sort the array using sort/sort_by/etc, and convert it back.

Given a sample.yml file of:

a: 1
c: 3
b: 2

then

yq 'to_entries | sort_by(.key) | reverse | from_entries' sample.yml

will output

c: 3
b: 2
a: 1

Use with_entries to filter the map

Given a sample.yml file of:

a:
  b: bird
c:
  d: dog

then

yq 'with_entries(select(.value | has("b")))' sample.yml

will output

a:
  b: bird

Env Variable Operators

These operators are used to handle environment variables usage in expressions and documents. While environment variables can, of course, be passed in via your CLI with string interpolation, this often comes with complex quote escaping and can be tricky to write and read.

There are three operators:

  • env which takes a single environment variable name and parse the variable as a yaml node (be it a map, array, string, number of boolean)
  • strenv which also takes a single environment variable name, and always parses the variable as a string.
  • envsubst which you pipe strings into and it interpolates environment variables in strings using envsubst.

EnvSubst Options

You can optionally pass envsubst any of the following options:

  • nu: NoUnset, this will fail if there are any referenced variables that are not set
  • ne: NoEmpty, this will fail if there are any referenced variables that are empty
  • ff: FailFast, this will abort on the first failure (rather than collect all the errors)

E.g: envsubst(ne, ff) will fail on the first empty variable.

See Imposing Restrictions in the envsubst documentation for more information, and below for examples.

Tip

To replace environment variables across all values in a document, envsubst can be used with the recursive descent operator as follows:

yq '(.. | select(tag == "!!str")) |= envsubst' file.yaml

Read string environment variable

Running

myenv="cat meow" yq --null-input '.a = env(myenv)'

will output

a: cat meow

Read boolean environment variable

Running

myenv="true" yq --null-input '.a = env(myenv)'

will output

a: true

Read numeric environment variable

Running

myenv="12" yq --null-input '.a = env(myenv)'

will output

a: 12

Read yaml environment variable

Running

myenv="{b: fish}" yq --null-input '.a = env(myenv)'

will output

a: {b: fish}

Read boolean environment variable as a string

Running

myenv="true" yq --null-input '.a = strenv(myenv)'

will output

a: "true"

Read numeric environment variable as a string

Running

myenv="12" yq --null-input '.a = strenv(myenv)'

will output

a: "12"

Dynamically update a path from an environment variable

The env variable can be any valid yq expression.

Given a sample.yml file of:

a:
  b:
    - name: dog
    - name: cat

then

pathEnv=".a.b[0].name"  valueEnv="moo" yq 'eval(strenv(pathEnv)) = strenv(valueEnv)' sample.yml

will output

a:
  b:
    - name: moo
    - name: cat

Dynamic key lookup with environment variable

Given a sample.yml file of:

cat: meow
dog: woof

then

myenv="cat" yq '.[env(myenv)]' sample.yml

will output

meow

Replace strings with envsubst

Running

myenv="cat" yq --null-input '"the ${myenv} meows" | envsubst'

will output

the cat meows

Replace strings with envsubst, missing variables

Running

yq --null-input '"the ${myenvnonexisting} meows" | envsubst'

will output

the  meows

Replace strings with envsubst(nu), missing variables

(nu) not unset, will fail if there are unset (missing) variables

Running

yq --null-input '"the ${myenvnonexisting} meows" | envsubst(nu)'

will output

Error: variable ${myenvnonexisting} not set

Replace strings with envsubst(ne), missing variables

(ne) not empty, only validates set variables

Running

yq --null-input '"the ${myenvnonexisting} meows" | envsubst(ne)'

will output

the  meows

Replace strings with envsubst(ne), empty variable

(ne) not empty, will fail if a references variable is empty

Running

myenv="" yq --null-input '"the ${myenv} meows" | envsubst(ne)'

will output

Error: variable ${myenv} set but empty

Replace strings with envsubst, missing variables with defaults

Running

yq --null-input '"the ${myenvnonexisting-dog} meows" | envsubst'

will output

the dog meows

Replace strings with envsubst(nu), missing variables with defaults

Having a default specified skips over the missing variable.

Running

yq --null-input '"the ${myenvnonexisting-dog} meows" | envsubst(nu)'

will output

the dog meows

Replace strings with envsubst(ne), missing variables with defaults

Fails, because the variable is explicitly set to blank.

Running

myEmptyEnv="" yq --null-input '"the ${myEmptyEnv-dog} meows" | envsubst(ne)'

will output

Error: variable ${myEmptyEnv} set but empty

Replace string environment variable in document

Given a sample.yml file of:

v: ${myenv}

then

myenv="cat meow" yq '.v |= envsubst' sample.yml

will output

v: cat meow

(Default) Return all envsubst errors

By default, all errors are returned at once.

Running

yq --null-input '"the ${notThere} ${alsoNotThere}" | envsubst(nu)'

will output

Error: variable ${notThere} not set
variable ${alsoNotThere} not set

Fail fast, return the first envsubst error (and abort)

Running

yq --null-input '"the ${notThere} ${alsoNotThere}" | envsubst(nu,ff)'

will output

Error: variable ${notThere} not set

Equals

This is a boolean operator that will return true if the LHS is equal to the RHS and false otherwise.

.a == .b

It is most often used with the select operator to find particular nodes:

select(.a == .b)

The not equals != operator returns false if the LHS is equal to the RHS.

  • comparison (>=, < etc) operators here
  • boolean operators (and, or, any etc) here
  • select operator here

Match string

Given a sample.yml file of:

- cat
- goat
- dog

then

yq '.[] | (. == "*at")' sample.yml

will output

true
true
false

Don’t match string

Given a sample.yml file of:

- cat
- goat
- dog

then

yq '.[] | (. != "*at")' sample.yml

will output

false
false
true

Match number

Given a sample.yml file of:

- 3
- 4
- 5

then

yq '.[] | (. == 4)' sample.yml

will output

false
true
false

Don’t match number

Given a sample.yml file of:

- 3
- 4
- 5

then

yq '.[] | (. != 4)' sample.yml

will output

true
false
true

Match nulls

Running

yq --null-input 'null == ~'

will output

true

Non existent key doesn’t equal a value

Given a sample.yml file of:

a: frog

then

yq 'select(.b != "thing")' sample.yml

will output

a: frog

Two non existent keys are equal

Given a sample.yml file of:

a: frog

then

yq 'select(.b == .c)' sample.yml

will output

a: frog

Eval

Use eval to dynamically process an expression - for instance from an environment variable.

eval takes a single argument, and evaluates that as a yq expression. Any valid expression can be used, be it a path .a.b.c | select(. == "cat"), or an update .a.b.c = "gogo".

Tip: This can be a useful way to parameterise complex scripts.

Dynamically evaluate a path

Given a sample.yml file of:

pathExp: .a.b[] | select(.name == "cat")
a:
  b:
    - name: dog
    - name: cat

then

yq 'eval(.pathExp)' sample.yml

will output

name: cat

Dynamically update a path from an environment variable

The env variable can be any valid yq expression.

Given a sample.yml file of:

a:
  b:
    - name: dog
    - name: cat

then

pathEnv=".a.b[0].name"  valueEnv="moo" yq 'eval(strenv(pathEnv)) = strenv(valueEnv)' sample.yml

will output

a:
  b:
    - name: moo
    - name: cat

File Operators

File operators are most often used with merge when needing to merge specific files together. Note that when doing this, you will need to use eval-all to ensure all yaml documents are loaded into memory before performing the merge (as opposed to eval which runs the expression once per document).

Note that the fileIndex operator has a short alias of fi.

Merging files

Note the use of eval-all to ensure all documents are loaded into memory.

yq eval-all 'select(fi == 0) * select(filename == "file2.yaml")' file1.yaml file2.yaml

Get filename

Given a sample.yml file of:

a: cat

then

yq 'filename' sample.yml

will output

sample.yml

Get file index

Given a sample.yml file of:

a: cat

then

yq 'file_index' sample.yml

will output

0

Get file indices of multiple documents

Given a sample.yml file of:

a: cat

And another sample another.yml file of:

a: cat

then

yq eval-all 'file_index' sample.yml another.yml

will output

0
1

Get file index alias

Given a sample.yml file of:

a: cat

then

yq 'fi' sample.yml

will output

0

Filter Operator

Filters an array (or map values) by the expression given. Equivalent to doing map(select(exp)).

Filter array

Given a sample.yml file of:

- 1
- 2
- 3

then

yq 'filter(. < 3)' sample.yml

will output

- 1
- 2

Filter map values

Given a sample.yml file of:

c:
  things: cool
  frog: yes
d:
  things: hot
  frog: false

then

yq 'filter(.things == "cool")' sample.yml

will output

- things: cool
  frog: yes

Flatten

This recursively flattens arrays.

Flatten

Recursively flattens all arrays

Given a sample.yml file of:

- 1
- - 2
- - - 3

then

yq 'flatten' sample.yml

will output

- 1
- 2
- 3

Flatten with depth of one

Given a sample.yml file of:

- 1
- - 2
- - - 3

then

yq 'flatten(1)' sample.yml

will output

- 1
- 2
- - 3

Flatten empty array

Given a sample.yml file of:

- []

then

yq 'flatten' sample.yml

will output

[]

Flatten array of objects

Given a sample.yml file of:

- foo: bar
- - foo: baz

then

yq 'flatten' sample.yml

will output

- foo: bar
- foo: baz

Group By

This is used to group items in an array by an expression.

Group by field

Given a sample.yml file of:

- foo: 1
  bar: 10
- foo: 3
  bar: 100
- foo: 1
  bar: 1

then

yq 'group_by(.foo)' sample.yml

will output

- - foo: 1
    bar: 10
  - foo: 1
    bar: 1
- - foo: 3
    bar: 100

Group by field, with nulls

Given a sample.yml file of:

- cat: dog
- foo: 1
  bar: 10
- foo: 3
  bar: 100
- no: foo for you
- foo: 1
  bar: 1

then

yq 'group_by(.foo)' sample.yml

will output

- - cat: dog
  - no: foo for you
- - foo: 1
    bar: 10
  - foo: 1
    bar: 1
- - foo: 3
    bar: 100

Has

This operation returns true if the key exists in a map (or index in an array), false otherwise.

Has map key

Given a sample.yml file of:

- a: yes
- a: ~
- a:
- b: nope

then

yq '.[] | has("a")' sample.yml

will output

true
true
true
false

Select, checking for existence of deep paths

Simply pipe in parent expressions into has

Given a sample.yml file of:

- a:
    b:
      c: cat
- a:
    b:
      d: dog

then

yq '.[] | select(.a.b | has("c"))' sample.yml

will output

a:
  b:
    c: cat

Has array index

Given a sample.yml file of:

- []
- [1]
- [1, 2]
- [1, null]
- [1, 2, 3]

then

yq '.[] | has(1)' sample.yml

will output

false
false
true
true
true

Keys

Use the keys operator to return map keys or array indices.

Map keys

Given a sample.yml file of:

dog: woof
cat: meow

then

yq 'keys' sample.yml

will output

- dog
- cat

Array keys

Given a sample.yml file of:

- apple
- banana

then

yq 'keys' sample.yml

will output

- 0
- 1

Retrieve array key

Given a sample.yml file of:

- 1
- 2
- 3

then

yq '.[1] | key' sample.yml

will output

1

Retrieve map key

Given a sample.yml file of:

a: thing

then

yq '.a | key' sample.yml

will output

a

No key

Given a sample.yml file of:

{}

then

yq 'key' sample.yml

will output

Update map key

Given a sample.yml file of:

a:
  x: 3
  y: 4

then

yq '(.a.x | key) = "meow"' sample.yml

will output

a:
  meow: 3
  y: 4

Get comment from map key

Given a sample.yml file of:

a:
  # comment on key
  x: 3
  y: 4

then

yq '.a.x | key | headComment' sample.yml

will output

comment on key

Check node is a key

Given a sample.yml file of:

a:
  b:
    - cat
  c: frog

then

yq '[... | { "p": path | join("."), "isKey": is_key, "tag": tag }]' sample.yml

will output

- p: ""
  isKey: false
  tag: '!!map'
- p: a
  isKey: true
  tag: '!!str'
- p: a
  isKey: false
  tag: '!!map'
- p: a.b
  isKey: true
  tag: '!!str'
- p: a.b
  isKey: false
  tag: '!!seq'
- p: a.b.0
  isKey: false
  tag: '!!str'
- p: a.c
  isKey: true
  tag: '!!str'
- p: a.c
  isKey: false
  tag: '!!str'

Kind

The kind operator identifies the type of a node as either scalar, map, or seq.

This can be used for filtering or transforming nodes based on their type.

Note that null values are treated as scalar.

Get kind

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f: []
g: {}
h: null

then

yq '.. | kind' sample.yml

will output

map
scalar
scalar
scalar
scalar
seq
map
scalar

Get kind, ignores custom tags

Unlike tag, kind is not affected by custom tags.

Given a sample.yml file of:

a: !!thing cat
b: !!foo {}
c: !!bar []

then

yq '.. | kind' sample.yml

will output

map
scalar
map
seq

Add comments only to scalars

An example of how you can use kind

Given a sample.yml file of:

a:
  b: 5
  c: 3.2
e: true
f: []
g: {}
h: null

then

yq '(.. | select(kind == "scalar")) line_comment = "this is a scalar"' sample.yml

will output

a:
  b: 5 # this is a scalar
  c: 3.2 # this is a scalar
e: true # this is a scalar
f: []
g: {}
h: null # this is a scalar

Length

Returns the lengths of the nodes. Length is defined according to the type of the node.

String length

returns length of string

Given a sample.yml file of:

a: cat

then

yq '.a | length' sample.yml

will output

3

null length

Given a sample.yml file of:

a: null

then

yq '.a | length' sample.yml

will output

0

Map length

returns number of entries

Given a sample.yml file of:

a: cat
c: dog

then

yq 'length' sample.yml

will output

2

Array length

returns number of elements

Given a sample.yml file of:

- 2
- 4
- 6
- 8

then

yq 'length' sample.yml

will output

4

Line

Returns the line of the matching node. Starts from 1, 0 indicates there was no line data.

Returns line of value node

Given a sample.yml file of:

a: cat
b:
  c: cat

then

yq '.b | line' sample.yml

will output

3

Returns line of key node

Pipe through the key operator to get the line of the key

Given a sample.yml file of:

a: cat
b:
  c: cat

then

yq '.b | key | line' sample.yml

will output

2

First line is 1

Given a sample.yml file of:

a: cat

then

yq '.a | line' sample.yml

will output

1

No line data is 0

Running

yq --null-input '{"a": "new entry"} | line'

will output

0

Load

The load operators allows you to load in content from another file.

Note that you can use string operators like + and sub to modify the value in the yaml file to a path that exists in your system.

You can load files of the following supported types:

Format Load Operator
Yaml load
XML load_xml
Properties load_props
Plain String load_str
Base64 load_base64

Note that load_base64 only works for base64 encoded utf-8 strings.

Samples files for tests:

yaml

../../examples/thing.yml:

a: apple is included
b: cool
xml

small.xml:

<this>is some xml</this>
properties

small.properties:

this.is = a properties file
base64

base64.txt:

bXkgc2VjcmV0IGNoaWxsaSByZWNpcGUgaXMuLi4u

Simple example

Given a sample.yml file of:

myFile: ../../examples/thing.yml

then

yq 'load(.myFile)' sample.yml

will output

a: apple is included
b: cool.

Replace node with referenced file

Note that you can modify the filename in the load operator if needed.

Given a sample.yml file of:

something:
  file: thing.yml

then

yq '.something |= load("../../examples/" + .file)' sample.yml

will output

something:
  a: apple is included
  b: cool.

Replace all nodes with referenced file

Recursively match all the nodes (..) and then filter the ones that have a ‘file’ attribute.

Given a sample.yml file of:

something:
  file: thing.yml
over:
  here:
    - file: thing.yml

then

yq '(.. | select(has("file"))) |= load("../../examples/" + .file)' sample.yml

will output

something:
  a: apple is included
  b: cool.
over:
  here:
    - a: apple is included
      b: cool.

Replace node with referenced file as string

This will work for any text based file

Given a sample.yml file of:

something:
  file: thing.yml

then

yq '.something |= load_str("../../examples/" + .file)' sample.yml

will output

something: |-
  a: apple is included
  b: cool.  

Load from XML

Given a sample.yml file of:

cool: things

then

yq '.more_stuff = load_xml("../../examples/small.xml")' sample.yml

will output

cool: things
more_stuff:
  this: is some xml

Load from Properties

Given a sample.yml file of:

cool: things

then

yq '.more_stuff = load_props("../../examples/small.properties")' sample.yml

will output

cool: things
more_stuff:
  this:
    is: a properties file

Merge from properties

This can be used as a convenient way to update a yaml document

Given a sample.yml file of:

this:
  is: from yaml
  cool: ay

then

yq '. *= load_props("../../examples/small.properties")' sample.yml

will output

this:
  is: a properties file
  cool: ay

Load from base64 encoded file

Given a sample.yml file of:

cool: things

then

yq '.more_stuff = load_base64("../../examples/base64.txt")' sample.yml

will output

cool: things
more_stuff: my secret chilli recipe is....

Min

Computes the minimum among an incoming sequence of scalar values.

Minimum int

Given a sample.yml file of:

- 99
- 16
- 12
- 6
- 66

then

yq 'min' sample.yml

will output

6

Minimum string

Given a sample.yml file of:

- foo
- bar
- baz

then

yq 'min' sample.yml

will output

bar

Minimum of empty

Given a sample.yml file of:

[]

then

yq 'min' sample.yml

will output

Map

Maps values of an array. Use map_values to map values of an object.

Map array

Given a sample.yml file of:

- 1
- 2
- 3

then

yq 'map(. + 1)' sample.yml

will output

- 2
- 3
- 4

Map object values

Given a sample.yml file of:

a: 1
b: 2
c: 3

then

yq 'map_values(. + 1)' sample.yml

will output

a: 2
b: 3
c: 4

Max

Computes the maximum among an incoming sequence of scalar values.

Maximum int

Given a sample.yml file of:

- 99
- 16
- 12
- 6
- 66

then

yq 'max' sample.yml

will output

99

Maximum string

Given a sample.yml file of:

- foo
- bar
- baz

then

yq 'max' sample.yml

will output

foo

Maximum of empty

Given a sample.yml file of:

[]

then

yq 'max' sample.yml

will output

Modulo

Arithmetic modulo operator, returns the remainder from dividing two numbers.

Number modulo - int

If the lhs and rhs are ints then the expression will be calculated with ints.

Given a sample.yml file of:

a: 13
b: 2

then

yq '.a = .a % .b' sample.yml

will output

a: 1
b: 2

Number modulo - float

If the lhs or rhs are floats then the expression will be calculated with floats.

Given a sample.yml file of:

a: 12
b: 2.5

then

yq '.a = .a % .b' sample.yml

will output

a: !!float 2
b: 2.5

Number modulo - int by zero

If the lhs is an int and rhs is a 0 the result is an error.

Given a sample.yml file of:

a: 1
b: 0

then

yq '.a = .a % .b' sample.yml

will output

Error: cannot modulo by 0

Number modulo - float by zero

If the lhs is a float and rhs is a 0 the result is NaN.

Given a sample.yml file of:

a: 1.1
b: 0

then

yq '.a = .a % .b' sample.yml

will output

a: !!float NaN
b: 0

Multiply (Merge)

Like the multiple operator in jq, depending on the operands, this multiply operator will do different things. Currently numbers, arrays and objects are supported.

Objects and arrays - merging

Objects are merged deeply matching on matching keys. By default, array values override and are not deeply merged.

You can use the add operator +, to shallow merge objects, see more info here.

Note that when merging objects, this operator returns the merged object (not the parent). This will be clearer in the examples below.

Merge Flags

You can control how objects are merged by using one or more of the following flags. Multiple flags can be used together, e.g. .a *+? .b. See examples below

  • + append arrays
  • d deeply merge arrays
  • ? only merge existing fields
  • n only merge new fields
  • c clobber custom tags

To perform a shallow merge only, use the add operator +, see more info here.

Merge two files together

This uses the load operator to merge file2 into file1.

yq '. *= load("file2.yml")' file1.yml
Merging all files

Note the use of eval-all to ensure all documents are loaded into memory.

yq eval-all '. as $item ireduce ({}; . * $item )' *.yml

Merging complex arrays together by a key field

By default - yq merge is naive. It merges maps when they match the key name, and arrays are merged either by appending them together, or merging the entries by their position in the array.

For more complex array merging (e.g. merging items that match on a certain key) please see the example here

Multiply integers

Given a sample.yml file of:

a: 3
b: 4

then

yq '.a *= .b' sample.yml

will output

a: 12
b: 4

Multiply string node X int

Given a sample.yml file of:

b: banana

then

yq '.b * 4' sample.yml

will output

bananabananabananabanana

Multiply int X string node

Given a sample.yml file of:

b: banana

then

yq '4 * .b' sample.yml

will output

bananabananabananabanana

Multiply string X int node

Given a sample.yml file of:

n: 4

then

yq '"banana" * .n' sample.yml

will output

bananabananabananabanana

Multiply int node X string

Given a sample.yml file of:

n: 4

then

yq '.n * "banana"' sample.yml

will output

bananabananabananabanana

Merge objects together, returning merged result only

Given a sample.yml file of:

a:
  field: me
  fieldA: cat
b:
  field:
    g: wizz
  fieldB: dog

then

yq '.a * .b' sample.yml

will output

field:
  g: wizz
fieldA: cat
fieldB: dog

Merge objects together, returning parent object

Given a sample.yml file of:

a:
  field: me
  fieldA: cat
b:
  field:
    g: wizz
  fieldB: dog

then

yq '. * {"a":.b}' sample.yml

will output

a:
  field:
    g: wizz
  fieldA: cat
  fieldB: dog
b:
  field:
    g: wizz
  fieldB: dog

Merge keeps style of LHS

Given a sample.yml file of:

a: {things: great}
b:
  also: "me"

then

yq '. * {"a":.b}' sample.yml

will output

a: {things: great, also: "me"}
b:
  also: "me"

Merge arrays

Given a sample.yml file of:

a:
  - 1
  - 2
  - 3
b:
  - 3
  - 4
  - 5

then

yq '. * {"a":.b}' sample.yml

will output

a:
  - 3
  - 4
  - 5
b:
  - 3
  - 4
  - 5

Merge, only existing fields

Given a sample.yml file of:

a:
  thing: one
  cat: frog
b:
  missing: two
  thing: two

then

yq '.a *? .b' sample.yml

will output

thing: two
cat: frog

Merge, only new fields

Given a sample.yml file of:

a:
  thing: one
  cat: frog
b:
  missing: two
  thing: two

then

yq '.a *n .b' sample.yml

will output

thing: one
cat: frog
missing: two

Merge, appending arrays

Given a sample.yml file of:

a:
  array:
    - 1
    - 2
    - animal: dog
  value: coconut
b:
  array:
    - 3
    - 4
    - animal: cat
  value: banana

then

yq '.a *+ .b' sample.yml

will output

array:
  - 1
  - 2
  - animal: dog
  - 3
  - 4
  - animal: cat
value: banana

Merge, only existing fields, appending arrays

Given a sample.yml file of:

a:
  thing:
    - 1
    - 2
b:
  thing:
    - 3
    - 4
  another:
    - 1

then

yq '.a *?+ .b' sample.yml

will output

thing:
  - 1
  - 2
  - 3
  - 4

Merge, deeply merging arrays

Merging arrays deeply means arrays are merged like objects, with indices as their key. In this case, we merge the first item in the array and do nothing with the second.

Given a sample.yml file of:

a:
  - name: fred
    age: 12
  - name: bob
    age: 32
b:
  - name: fred
    age: 34

then

yq '.a *d .b' sample.yml

will output

- name: fred
  age: 34
- name: bob
  age: 32

Merge arrays of objects together, matching on a key

This is a fairly complex expression - you can use it as is by providing the environment variables as seen in the example below.

It merges in the array provided in the second file into the first - matching on equal keys.

Explanation:

The approach, at a high level, is to reduce into a merged map (keyed by the unique key) and then convert that back into an array.

First the expression will create a map from the arrays keyed by the idPath, the unique field we want to merge by. The reduce operator is merging ‘({}; . * $item )’, so array elements with the matching key will be merged together.

Next, we convert the map back to an array, using reduce again, concatenating all the map values together.

Finally, we set the result of the merged array back into the first doc.

Thanks Kev from stackoverflow

Given a sample.yml file of:

myArray:
  - a: apple
    b: appleB
  - a: kiwi
    b: kiwiB
  - a: banana
    b: bananaB
something: else

And another sample another.yml file of:

newArray:
  - a: banana
    c: bananaC
  - a: apple
    b: appleB2
  - a: dingo
    c: dingoC

then

idPath=".a"  originalPath=".myArray"  otherPath=".newArray" yq eval-all '
(
  (( (eval(strenv(originalPath)) + eval(strenv(otherPath)))  | .[] | {(eval(strenv(idPath))):  .}) as $item ireduce ({}; . * $item )) as $uniqueMap
  | ( $uniqueMap  | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | (eval(strenv(originalPath))) = $mergedArray
' sample.yml another.yml

will output

myArray:
  - a: apple
    b: appleB2
  - a: kiwi
    b: kiwiB
  - a: banana
    b: bananaB
    c: bananaC
  - a: dingo
    c: dingoC
something: else

Merge to prefix an element

Given a sample.yml file of:

a: cat
b: dog

then

yq '. * {"a": {"c": .a}}' sample.yml

will output

a:
  c: cat
b: dog

Merge with simple aliases

Given a sample.yml file of:

a: &cat
  c: frog
b:
  f: *cat
c:
  g: thongs

then

yq '.c * .b' sample.yml

will output

g: thongs
f: *cat

Merge copies anchor names

Given a sample.yml file of:

a:
  c: &cat frog
b:
  f: *cat
c:
  g: thongs

then

yq '.c * .a' sample.yml

will output

g: thongs
c: &cat frog

Merge with merge anchors

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar * .foobarList' sample.yml

will output

c: foobarList_c
!!merge <<:
  - *foo
  - *bar
thing: foobar_thing
b: foobarList_b

Custom types: that are really numbers

When custom tags are encountered, yq will try to decode the underlying type.

Given a sample.yml file of:

a: !horse 2
b: !goat 3

then

yq '.a = .a * .b' sample.yml

will output

a: !horse 6
b: !goat 3

Custom types: that are really maps

Custom tags will be maintained.

Given a sample.yml file of:

a: !horse
  cat: meow
b: !goat
  dog: woof

then

yq '.a = .a * .b' sample.yml

will output

a: !horse
  cat: meow
  dog: woof
b: !goat
  dog: woof

Custom types: clobber tags

Use the c option to clobber custom tags. Note that the second tag is now used.

Given a sample.yml file of:

a: !horse
  cat: meow
b: !goat
  dog: woof

then

yq '.a *=c .b' sample.yml

will output

a: !goat
  cat: meow
  dog: woof
b: !goat
  dog: woof

Merging a null with a map

Running

yq --null-input 'null * {"some": "thing"}'

will output

some: thing

Merging a map with null

Running

yq --null-input '{"some": "thing"} * null'

will output

some: thing

Merging a null with an array

Running

yq --null-input 'null * ["some"]'

will output

- some

Merging an array with null

Running

yq --null-input '["some"] * null'

will output

- some

Omit

Works like pick, but instead you specify the keys/indices that you don’t want included.

Omit keys from map

Note that non existent keys are skipped.

Given a sample.yml file of:

myMap:
  cat: meow
  dog: bark
  thing: hamster
  hamster: squeak

then

yq '.myMap |= omit(["hamster", "cat", "goat"])' sample.yml

will output

myMap:
  dog: bark
  thing: hamster

Omit indices from array

Note that non existent indices are skipped.

Given a sample.yml file of:

- cat
- leopard
- lion

then

yq 'omit([2, 0, 734, -5])' sample.yml

will output

- leopard

Parent

Parent simply returns the parent nodes of the matching nodes.

Simple example

Given a sample.yml file of:

a:
  nested: cat

then

yq '.a.nested | parent' sample.yml

will output

nested: cat

Parent of nested matches

Given a sample.yml file of:

a:
  fruit: apple
  name: bob
b:
  fruit: banana
  name: sam

then

yq '.. | select(. == "banana") | parent' sample.yml

will output

fruit: banana
name: sam

Get parent attribute

Given a sample.yml file of:

a:
  fruit: apple
  name: bob
b:
  fruit: banana
  name: sam

then

yq '.. | select(. == "banana") | parent.name' sample.yml

will output

sam

N-th parent

You can optionally supply the number of levels to go up for the parent, the default being 1.

Given a sample.yml file of:

a:
  b:
    c: cat

then

yq '.a.b.c | parent(2)' sample.yml

will output

b:
  c: cat

N-th parent - another level

Given a sample.yml file of:

a:
  b:
    c: cat

then

yq '.a.b.c | parent(3)' sample.yml

will output

a:
  b:
    c: cat

No parent

Given a sample.yml file of:

{}

then

yq 'parent' sample.yml

will output

Path

The path operator can be used to get the traversal paths of matching nodes in an expression. The path is returned as an array, which if traversed in order will lead to the matching node.

You can get the key/index of matching nodes by using the path operator to return the path array then piping that through .[-1] to get the last element of that array, the key.

Use setpath to set a value to the path array returned by path, and similarly delpaths for an array of path arrays.

Map path

Given a sample.yml file of:

a:
  b: cat

then

yq '.a.b | path' sample.yml

will output

- a
- b

Get map key

Given a sample.yml file of:

a:
  b: cat

then

yq '.a.b | path | .[-1]' sample.yml

will output

b

Array path

Given a sample.yml file of:

a:
  - cat
  - dog

then

yq '.a.[] | select(. == "dog") | path' sample.yml

will output

- a
- 1

Get array index

Given a sample.yml file of:

a:
  - cat
  - dog

then

yq '.a.[] | select(. == "dog") | path | .[-1]' sample.yml

will output

1

Given a sample.yml file of:

a:
  - cat
  - dog
  - frog

then

yq '.a[] | select(. == "*og") | [{"path":path, "value":.}]' sample.yml

will output

- path:
    - a
    - 1
  value: dog
- path:
    - a
    - 2
  value: frog

Set path

Given a sample.yml file of:

a:
  b: cat

then

yq 'setpath(["a", "b"]; "things")' sample.yml

will output

a:
  b: things

Set on empty document

Running

yq --null-input 'setpath(["a", "b"]; "things")'

will output

a:
  b: things

Set path to prune deep paths

Like pick but recursive. This uses ireduce to deeply set the selected paths into an empty object.

Given a sample.yml file of:


parentA: bob
parentB:
  child1: i am child1
  child2: i am child2
parentC:
  child1: me child1
  child2: me child2

then

yq '(.parentB.child2, .parentC.child1) as $i
  ireduce({}; setpath($i | path; $i))' sample.yml

will output

parentB:
  child2: i am child2
parentC:
  child1: me child1

Set array path

Given a sample.yml file of:

a:
  - cat
  - frog

then

yq 'setpath(["a", 0]; "things")' sample.yml

will output

a:
  - things
  - frog

Set array path empty

Running

yq --null-input 'setpath(["a", 0]; "things")'

will output

a:
  - things

Delete path

Notice delpaths takes an array of paths.

Given a sample.yml file of:

a:
  b: cat
  c: dog
  d: frog

then

yq 'delpaths([["a", "c"], ["a", "d"]])' sample.yml

will output

a:
  b: cat

Delete array path

Given a sample.yml file of:

a:
  - cat
  - frog

then

yq 'delpaths([["a", 0]])' sample.yml

will output

a:
  - frog

Delete - wrong parameter

delpaths does not work with a single path array

Given a sample.yml file of:

a:
  - cat
  - frog

then

yq 'delpaths(["a", 0])' sample.yml

will output

Error: DELPATHS: expected entry [0] to be a sequence, but its a !!str. Note that delpaths takes an array of path arrays, e.g. [["a", "b"]]

Pick

Filter a map by the specified list of keys. Map is returned with the key in the order of the pick list.

Similarly, filter an array by the specified list of indices.

Pick keys from map

Note that the order of the keys matches the pick order and non existent keys are skipped.

Given a sample.yml file of:

myMap:
  cat: meow
  dog: bark
  thing: hamster
  hamster: squeak

then

yq '.myMap |= pick(["hamster", "cat", "goat"])' sample.yml

will output

myMap:
  hamster: squeak
  cat: meow

Pick keys from map, included all the keys

We create a map of the picked keys plus all the current keys, and run that through unique

Given a sample.yml file of:

myMap:
  cat: meow
  dog: bark
  thing: hamster
  hamster: squeak

then

yq '.myMap |= pick( (["thing"] + keys) | unique)' sample.yml

will output

myMap:
  thing: hamster
  cat: meow
  dog: bark
  hamster: squeak

Pick indices from array

Note that the order of the indices matches the pick order and non existent indices are skipped.

Given a sample.yml file of:

- cat
- leopard
- lion

then

yq 'pick([2, 0, 734, -5])' sample.yml

will output

- lion
- cat

Pipe

Pipe the results of an expression into another. Like the bash operator.

Simple Pipe

Given a sample.yml file of:

a:
  b: cat

then

yq '.a | .b' sample.yml

will output

cat

Multiple updates

Given a sample.yml file of:

a: cow
b: sheep
c: same

then

yq '.a = "cat" | .b = "dog"' sample.yml

will output

a: cat
b: dog
c: same

Pivot

Emulates the PIVOT function supported by several popular RDBMS systems.

Pivot a sequence of sequences

Given a sample.yml file of:

- - foo
  - bar
  - baz
- - sis
  - boom
  - bah

then

yq 'pivot' sample.yml

will output

- - foo
  - sis
- - bar
  - boom
- - baz
  - bah

Pivot sequence of heterogeneous sequences

Missing values are “padded” to null.

Given a sample.yml file of:

- - foo
  - bar
  - baz
- - sis
  - boom
  - bah
  - blah

then

yq 'pivot' sample.yml

will output

- - foo
  - sis
- - bar
  - boom
- - baz
  - bah
- -
  - blah

Pivot sequence of maps

Given a sample.yml file of:

- foo: a
  bar: b
  baz: c
- foo: x
  bar: y
  baz: z

then

yq 'pivot' sample.yml

will output

foo:
  - a
  - x
bar:
  - b
  - y
baz:
  - c
  - z

Pivot sequence of heterogeneous maps

Missing values are “padded” to null.

Given a sample.yml file of:

- foo: a
  bar: b
  baz: c
- foo: x
  bar: y
  baz: z
  what: ever

then

yq 'pivot' sample.yml

will output

foo:
  - a
  - x
bar:
  - b
  - y
baz:
  - c
  - z
what:
  -
  - ever

Recursive Descent (Glob)

This operator recursively matches (or globs) all children nodes given of a particular element, including that node itself. This is most often used to apply a filter recursively against all matches.

match values form ..

This will, like the jq equivalent, recursively match all value nodes. Use it to find/manipulate particular values.

For instance to set the style of all value nodes in a yaml doc, excluding map keys:

yq '.. style= "flow"' file.yaml

match values and map keys form ...

The also includes map keys in the results set. This is particularly useful in YAML as unlike JSON, map keys can have their own styling and tags and also use anchors and aliases.

For instance to set the style of all nodes in a yaml doc, including the map keys:

yq '... style= "flow"' file.yaml

Recurse map (values only)

Given a sample.yml file of:

a: frog

then

yq '..' sample.yml

will output

a: frog
frog

Recursively find nodes with keys

Note that this example has wrapped the expression in [] to show that there are two matches returned. You do not have to wrap in [] in your path expression.

Given a sample.yml file of:

a:
  name: frog
  b:
    name: blog
    age: 12

then

yq '[.. | select(has("name"))]' sample.yml

will output

- name: frog
  b:
    name: blog
    age: 12
- name: blog
  age: 12

Recursively find nodes with values

Given a sample.yml file of:

a:
  nameA: frog
  b:
    nameB: frog
    age: 12

then

yq '.. | select(. == "frog")' sample.yml

will output

frog
frog

Recurse map (values and keys)

Note that the map key appears in the results

Given a sample.yml file of:

a: frog

then

yq '...' sample.yml

will output

a: frog
a
frog

Aliases are not traversed

Given a sample.yml file of:

a: &cat
  c: frog
b: *cat

then

yq '[..]' sample.yml

will output

- a: &cat
    c: frog
  b: *cat
- &cat
  c: frog
- frog
- *cat

Merge docs are not traversed

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar | [..]' sample.yml

will output

- c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing
- foobar_c
- *foo
- foobar_thing

Reduce

Reduce is a powerful way to process a collection of data into a new form.

<exp> as $<name> ireduce (<init>; <block>)

e.g.

.[] as $item ireduce (0; . + $item)

On the LHS we are configuring the collection of items that will be reduced <exp> as well as what each element will be called $<name>. Note that the array has been splatted into its individual elements.

On the RHS there is <init>, the starting value of the accumulator and <block>, the expression that will update the accumulator for each element in the collection. Note that within the block expression, . will evaluate to the current value of the accumulator.

yq vs jq syntax

Reduce syntax in yq is a little different from jq - as yq (currently) isn’t as sophisticated as jq and its only supports infix notation (e.g. a + b, where the operator is in the middle of the two parameters) - where as jq uses a mix of infix notation with prefix notation (e.g. reduce a b is like writing + a b).

To that end, the reduce operator is called ireduce for backwards compatibility if a jq like prefix version of reduce is ever added.

Sum numbers

Given a sample.yml file of:

- 10
- 2
- 5
- 3

then

yq '.[] as $item ireduce (0; . + $item)' sample.yml

will output

20

Merge all yaml files together

Given a sample.yml file of:

a: cat

And another sample another.yml file of:

b: dog

then

yq eval-all '. as $item ireduce ({}; . * $item )' sample.yml another.yml

will output

a: cat
b: dog

Convert an array to an object

Given a sample.yml file of:

- name: Cathy
  has: apples
- name: Bob
  has: bananas

then

yq '.[] as $item ireduce ({}; .[$item | .name] = ($item | .has) )' sample.yml

will output

Cathy: apples
Bob: bananas

Reverse

Reverses the order of the items in an array

Reverse

Given a sample.yml file of:

- 1
- 2
- 3

then

yq 'reverse' sample.yml

will output

- 3
- 2
- 1

Sort descending by string field

Use sort with reverse to sort in descending order.

Given a sample.yml file of:

- a: banana
- a: cat
- a: apple

then

yq 'sort_by(.a) | reverse' sample.yml

will output

- a: cat
- a: banana
- a: apple

Select

Select is used to filter arrays and maps by a boolean expression.

  • equals / not equals (==, !=) operators here
  • comparison (>=, < etc) operators here
  • boolean operators (and, or, any etc) here

Select elements from array using wildcard prefix

Given a sample.yml file of:

- cat
- goat
- dog

then

yq '.[] | select(. == "*at")' sample.yml

will output

cat
goat

Select elements from array using wildcard suffix

Given a sample.yml file of:

- go-kart
- goat
- dog

then

yq '.[] | select(. == "go*")' sample.yml

will output

go-kart
goat

Select elements from array using wildcard prefix and suffix

Given a sample.yml file of:

- ago
- go
- meow
- going

then

yq '.[] | select(. == "*go*")' sample.yml

will output

ago
go
going

Select elements from array with regular expression

See more regular expression examples under the string operator docs.

Given a sample.yml file of:

- this_0
- not_this
- nor_0_this
- thisTo_4

then

yq '.[] | select(test("[a-zA-Z]+_[0-9]$"))' sample.yml

will output

this_0
thisTo_4

Select items from a map

Given a sample.yml file of:

things: cat
bob: goat
horse: dog

then

yq '.[] | select(. == "cat" or test("og$"))' sample.yml

will output

cat
dog

Use select and with_entries to filter map keys

Given a sample.yml file of:

name: bob
legs: 2
game: poker

then

yq 'with_entries(select(.key | test("ame$")))' sample.yml

will output

name: bob
game: poker

Select multiple items in a map and update

Note the brackets around the entire LHS.

Given a sample.yml file of:

a:
  things: cat
  bob: goat
  horse: dog

then

yq '(.a.[] | select(. == "cat" or . == "goat")) |= "rabbit"' sample.yml

will output

a:
  things: rabbit
  bob: rabbit
  horse: dog

Shuffle

Shuffles an array. Note that this command does not use a cryptographically secure random number generator to randomise the array order.

Shuffle array

Given a sample.yml file of:

- 1
- 2
- 3
- 4
- 5

then

yq 'shuffle' sample.yml

will output

- 5
- 2
- 4
- 1
- 3

Shuffle array in place

Given a sample.yml file of:

cool:
  - 1
  - 2
  - 3
  - 4
  - 5

then

yq '.cool |= shuffle' sample.yml

will output

cool:
  - 5
  - 2
  - 4
  - 1
  - 3

Slice Array

The slice array operator takes an array as input and returns a subarray. Like the jq equivalent, .[10:15] will return an array of length 5, starting from index 10 inclusive, up to index 15 exclusive. Negative numbers count backwards from the end of the array.

You may leave out the first or second number, which will refer to the start or end of the array respectively.

Slicing arrays

Given a sample.yml file of:

- cat
- dog
- frog
- cow

then

yq '.[1:3]' sample.yml

will output

- dog
- frog

Slicing arrays - without the first number

Starts from the start of the array

Given a sample.yml file of:

- cat
- dog
- frog
- cow

then

yq '.[:2]' sample.yml

will output

- cat
- dog

Slicing arrays - without the second number

Finishes at the end of the array

Given a sample.yml file of:

- cat
- dog
- frog
- cow

then

yq '.[2:]' sample.yml

will output

- frog
- cow

Slicing arrays - use negative numbers to count backwards from the end

Given a sample.yml file of:

- cat
- dog
- frog
- cow

then

yq '.[1:-1]' sample.yml

will output

- dog
- frog

Inserting into the middle of an array

using an expression to find the index

Given a sample.yml file of:

- cat
- dog
- frog
- cow

then

yq '(.[] | select(. == "dog") | key + 1) as $pos | .[0:($pos)] + ["rabbit"] + .[$pos:]' sample.yml

will output

- cat
- dog
- rabbit
- frog
- cow

Sort

Sorts an array. Use sort to sort an array as is, or sort_by(exp) to sort by a particular expression (e.g. subfield).

To sort by descending order, pipe the results through the reverse operator after sorting.

Note that at this stage, yq only sorts scalar fields.

Sort by string field

Given a sample.yml file of:

- a: banana
- a: cat
- a: apple

then

yq 'sort_by(.a)' sample.yml

will output

- a: apple
- a: banana
- a: cat

Sort by multiple fields

Given a sample.yml file of:

- a: dog
- a: cat
  b: banana
- a: cat
  b: apple

then

yq 'sort_by(.a, .b)' sample.yml

will output

- a: cat
  b: apple
- a: cat
  b: banana
- a: dog

Sort descending by string field

Use sort with reverse to sort in descending order.

Given a sample.yml file of:

- a: banana
- a: cat
- a: apple

then

yq 'sort_by(.a) | reverse' sample.yml

will output

- a: cat
- a: banana
- a: apple

Sort array in place

Given a sample.yml file of:

cool:
  - a: banana
  - a: cat
  - a: apple

then

yq '.cool |= sort_by(.a)' sample.yml

will output

cool:
  - a: apple
  - a: banana
  - a: cat

Sort array of objects by key

Note that you can give sort_by complex expressions, not just paths

Given a sample.yml file of:

cool:
  - b: banana
  - a: banana
  - c: banana

then

yq '.cool |= sort_by(keys | .[0])' sample.yml

will output

cool:
  - a: banana
  - b: banana
  - c: banana

Sort a map

Sorting a map, by default this will sort by the values

Given a sample.yml file of:

y: b
z: a
x: c

then

yq 'sort' sample.yml

will output

z: a
y: b
x: c

Sort a map by keys

Use sort_by to sort a map using a custom function

Given a sample.yml file of:

Y: b
z: a
x: c

then

yq 'sort_by(key | downcase)' sample.yml

will output

x: c
Y: b
z: a

Sort is stable

Note the order of the elements in unchanged when equal in sorting.

Given a sample.yml file of:

- a: banana
  b: 1
- a: banana
  b: 2
- a: banana
  b: 3
- a: banana
  b: 4

then

yq 'sort_by(.a)' sample.yml

will output

- a: banana
  b: 1
- a: banana
  b: 2
- a: banana
  b: 3
- a: banana
  b: 4

Sort by numeric field

Given a sample.yml file of:

- a: 10
- a: 100
- a: 1

then

yq 'sort_by(.a)' sample.yml

will output

- a: 1
- a: 10
- a: 100

Sort by custom date field

Given a sample.yml file of:

- a: 12-Jun-2011
- a: 23-Dec-2010
- a: 10-Aug-2011

then

yq 'with_dtf("02-Jan-2006"; sort_by(.a))' sample.yml

will output

- a: 23-Dec-2010
- a: 12-Jun-2011
- a: 10-Aug-2011

Sort, nulls come first

Given a sample.yml file of:

- 8
- 3
- null
- 6
- true
- false
- cat

then

yq 'sort' sample.yml

will output

- null
- false
- true
- 3
- 6
- 8
- cat

Sort Keys

The Sort Keys operator sorts maps by their keys (based on their string value). This operator does not do anything to arrays or scalars (so you can easily recursively apply it to all maps).

Sort is particularly useful for diffing two different yaml documents:

yq -i -P 'sort_keys(..)' file1.yml
yq -i -P 'sort_keys(..)' file2.yml
diff file1.yml file2.yml

Note that yq does not yet consider anchors when sorting by keys - this may result in invalid yaml documents if you are using merge anchors.

For more advanced sorting, you can use the sort_by function on a map, and give it a custom function like sort_by(key | downcase).

Sort keys of map

Given a sample.yml file of:

c: frog
a: blah
b: bing

then

yq 'sort_keys(.)' sample.yml

will output

a: blah
b: bing
c: frog

Sort keys recursively

Note the array elements are left unsorted, but maps inside arrays are sorted

Given a sample.yml file of:

bParent:
  c: dog
  array:
    - 3
    - 1
    - 2
aParent:
  z: donkey
  x:
    - c: yum
      b: delish
    - b: ew
      a: apple

then

yq 'sort_keys(..)' sample.yml

will output

aParent:
  x:
    - b: delish
      c: yum
    - a: apple
      b: ew
  z: donkey
bParent:
  array:
    - 3
    - 1
    - 2
  c: dog

Split into Documents

This operator splits all matches into separate documents

Split empty

Running

yq --null-input 'split_doc'

will output

Split array

Given a sample.yml file of:

- a: cat
- b: dog

then

yq '.[] | split_doc' sample.yml

will output

a: cat
---
b: dog

String Operators

RegEx

This uses Golang’s native regex functions under the hood - See their docs for the supported syntax.

Case insensitive tip: prefix the regex with (?i) - e.g. test("(?i)cats)".

match(regEx)

This operator returns the substring match details of the given regEx.

capture(regEx)

Capture returns named RegEx capture groups in a map. Can be more convenient than match depending on what you are doing.

test(regEx)

Returns true if the string matches the RegEx, false otherwise.

sub(regEx, replacement)

Substitutes matched substrings. The first parameter is the regEx to match substrings within the original string. The second parameter specifies what to replace those matches with. This can refer to capture groups from the first RegEx.

String blocks, bash and newlines

Bash is notorious for chomping on precious trailing newline characters, making it tricky to set strings with newlines properly. In particular, the $( exp ) will trim trailing newlines.

For instance to get this yaml:

a: |
  cat

Using $( exp ) wont work, as it will trim the trailing newline.

m=$(echo "cat\n") yq -n '.a = strenv(m)'
a: cat

However, using printf works:

printf -v m "cat\n" ; m="$m" yq -n '.a = strenv(m)'
a: |
  cat

As well as having multiline expressions:

m="cat
"  yq -n '.a = strenv(m)'
a: |
  cat

Similarly, if you’re trying to set the content from a file, and want a trailing newline:

IFS= read -rd '' output < <(cat my_file)
output=$output ./yq '.data.values = strenv(output)' first.yml

Interpolation

Given a sample.yml file of:

value: things
another: stuff

then

yq '.message = "I like \(.value) and \(.another)"' sample.yml

will output

value: things
another: stuff
message: I like things and stuff

Interpolation - not a string

Given a sample.yml file of:

value:
  an: apple

then

yq '.message = "I like \(.value)"' sample.yml

will output

value:
  an: apple
message: 'I like an: apple'

To up (upper) case

Works with unicode characters

Given a sample.yml file of:

água

then

yq 'upcase' sample.yml

will output

ÁGUA

To down (lower) case

Works with unicode characters

Given a sample.yml file of:

ÁgUA

then

yq 'downcase' sample.yml

will output

água

Join strings

Given a sample.yml file of:

- cat
- meow
- 1
- null
- true

then

yq 'join("; ")' sample.yml

will output

cat; meow; 1; ; true

Trim strings

Given a sample.yml file of:

- ' cat'
- 'dog '
- ' cow cow '
- horse

then

yq '.[] | trim' sample.yml

will output

cat
dog
cow cow
horse

Match string

Given a sample.yml file of:

foo bar foo

then

yq 'match("foo")' sample.yml

will output

string: foo
offset: 0
length: 3
captures: []

Match string, case insensitive

Given a sample.yml file of:

foo bar FOO

then

yq '[match("(?i)foo"; "g")]' sample.yml

will output

- string: foo
  offset: 0
  length: 3
  captures: []
- string: FOO
  offset: 8
  length: 3
  captures: []

Match with global capture group

Given a sample.yml file of:

abc abc

then

yq '[match("(ab)(c)"; "g")]' sample.yml

will output

- string: abc
  offset: 0
  length: 3
  captures:
    - string: ab
      offset: 0
      length: 2
    - string: c
      offset: 2
      length: 1
- string: abc
  offset: 4
  length: 3
  captures:
    - string: ab
      offset: 4
      length: 2
    - string: c
      offset: 6
      length: 1

Match with named capture groups

Given a sample.yml file of:

foo bar foo foo  foo

then

yq '[match("foo (?P<bar123>bar)? foo"; "g")]' sample.yml

will output

- string: foo bar foo
  offset: 0
  length: 11
  captures:
    - string: bar
      offset: 4
      length: 3
      name: bar123
- string: foo  foo
  offset: 12
  length: 8
  captures:
    - string: null
      offset: -1
      length: 0
      name: bar123

Capture named groups into a map

Given a sample.yml file of:

xyzzy-14

then

yq 'capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")' sample.yml

will output

a: xyzzy
n: "14"

Match without global flag

Given a sample.yml file of:

cat cat

then

yq 'match("cat")' sample.yml

will output

string: cat
offset: 0
length: 3
captures: []

Match with global flag

Given a sample.yml file of:

cat cat

then

yq '[match("cat"; "g")]' sample.yml

will output

- string: cat
  offset: 0
  length: 3
  captures: []
- string: cat
  offset: 4
  length: 3
  captures: []

Test using regex

Like jq’s equivalent, this works like match but only returns true/false instead of full match details

Given a sample.yml file of:

- cat
- dog

then

yq '.[] | test("at")' sample.yml

will output

true
false

Substitute / Replace string

This uses Golang’s regex, described here. Note the use of |= to run in context of the current string value.

Given a sample.yml file of:

a: dogs are great

then

yq '.a |= sub("dogs", "cats")' sample.yml

will output

a: cats are great

Substitute / Replace string with regex

This uses Golang’s regex, described here. Note the use of |= to run in context of the current string value.

Given a sample.yml file of:

a: cat
b: heat

then

yq '.[] |= sub("(a)", "${1}r")' sample.yml

will output

a: cart
b: heart

Custom types: that are really strings

When custom tags are encountered, yq will try to decode the underlying type.

Given a sample.yml file of:

a: !horse cat
b: !goat heat

then

yq '.[] |= sub("(a)", "${1}r")' sample.yml

will output

a: !horse cart
b: !goat heart

Split strings

Given a sample.yml file of:

cat; meow; 1; ; true

then

yq 'split("; ")' sample.yml

will output

- cat
- meow
- "1"
- ""
- "true"

Split strings one match

Given a sample.yml file of:

word

then

yq 'split("; ")' sample.yml

will output

- word

To string

Note that you may want to force yq to leave scalar values wrapped by passing in --unwrapScalar=false or -r=f

Given a sample.yml file of:

- 1
- true
- null
- ~
- cat
- an: object
- - array
  - 2

then

yq '.[] |= to_string' sample.yml

will output

- "1"
- "true"
- "null"
- "~"
- cat
- "an: object"
- "- array\n- 2"

Style

The style operator can be used to get or set the style of nodes (e.g. string style, yaml style). Use this to control the formatting of the document in yaml.

Update and set style of a particular node (simple)

Given a sample.yml file of:

a:
  b: thing
  c: something

then

yq '.a.b = "new" | .a.b style="double"' sample.yml

will output

a:
  b: "new"
  c: something

Update and set style of a particular node using path variables

Given a sample.yml file of:

a:
  b: thing
  c: something

then

yq 'with(.a.b ; . = "new" | . style="double")' sample.yml

will output

a:
  b: "new"
  c: something

Set tagged style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="tagged"' sample.yml

will output

!!map
a: !!str cat
b: !!int 5
c: !!float 3.2
e: !!bool true
f: !!seq
  - !!int 1
  - !!int 2
  - !!int 3
g: !!map
  something: !!str cool

Set double quote style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="double"' sample.yml

will output

a: "cat"
b: "5"
c: "3.2"
e: "true"
f:
  - "1"
  - "2"
  - "3"
g:
  something: "cool"

Set double quote style on map keys too

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '... style="double"' sample.yml

will output

"a": "cat"
"b": "5"
"c": "3.2"
"e": "true"
"f":
  - "1"
  - "2"
  - "3"
"g":
  "something": "cool"

Set single quote style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="single"' sample.yml

will output

a: 'cat'
b: '5'
c: '3.2'
e: 'true'
f:
  - '1'
  - '2'
  - '3'
g:
  something: 'cool'

Set literal quote style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="literal"' sample.yml

will output

a: |-
  cat  
b: |-
  5  
c: |-
  3.2  
e: |-
  true  
f:
  - |-
    1    
  - |-
    2    
  - |-
    3    
g:
  something: |-
    cool    

Set folded quote style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="folded"' sample.yml

will output

a: >-
  cat  
b: >-
  5  
c: >-
  3.2  
e: >-
  true  
f:
  - >-
    1    
  - >-
    2    
  - >-
    3    
g:
  something: >-
    cool    

Set flow quote style

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

then

yq '.. style="flow"' sample.yml

will output

{a: cat, b: 5, c: 3.2, e: true, f: [1, 2, 3], g: {something: cool}}

Reset style - or pretty print

Set empty (default) quote style, note the usage of ... to match keys too. Note that there is a --prettyPrint/-P short flag for this.

Given a sample.yml file of:

{a: cat, "b": 5, 'c': 3.2, "e": true,  f: [1,2,3], "g": { something: "cool"} }

then

yq '... style=""' sample.yml

will output

a: cat
b: 5
c: 3.2
e: true
f:
  - 1
  - 2
  - 3
g:
  something: cool

Set style relatively with assign-update

Given a sample.yml file of:

a: single
b: double

then

yq '.[] style |= .' sample.yml

will output

a: 'single'
b: "double"

Read style

Given a sample.yml file of:

{a: "cat", b: 'thing'}

then

yq '.. | style' sample.yml

will output

flow
double
single

Subtract

You can use subtract to subtract numbers as well as remove elements from an array.

Array subtraction

Running

yq --null-input '[1,2] - [2,3]'

will output

- 1

Array subtraction with nested array

Running

yq --null-input '[[1], 1, 2] - [[1], 3]'

will output

- 1
- 2

Array subtraction with nested object

Note that order of the keys does not matter

Given a sample.yml file of:

- a: b
  c: d
- a: b

then

yq '. - [{"c": "d", "a": "b"}]' sample.yml

will output

- a: b

Number subtraction - float

If the lhs or rhs are floats then the expression will be calculated with floats.

Given a sample.yml file of:

a: 3
b: 4.5

then

yq '.a = .a - .b' sample.yml

will output

a: -1.5
b: 4.5

Number subtraction - int

If both the lhs and rhs are ints then the expression will be calculated with ints.

Given a sample.yml file of:

a: 3
b: 4

then

yq '.a = .a - .b' sample.yml

will output

a: -1
b: 4

Decrement numbers

Given a sample.yml file of:

a: 3
b: 5

then

yq '.[] -= 1' sample.yml

will output

a: 2
b: 4

Date subtraction

You can subtract durations from dates. Assumes RFC3339 date time format, see date-time operators for more information.

Given a sample.yml file of:

a: 2021-01-01T03:10:00Z

then

yq '.a -= "3h10m"' sample.yml

will output

a: 2021-01-01T00:00:00Z

Date subtraction - custom format

Use with_dtf to specify your datetime format. See date-time operators for more information.

Given a sample.yml file of:

a: Saturday, 15-Dec-01 at 6:00AM GMT

then

yq 'with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a -= "3h1m")' sample.yml

will output

a: Saturday, 15-Dec-01 at 2:59AM GMT

Custom types: that are really numbers

When custom tags are encountered, yq will try to decode the underlying type.

Given a sample.yml file of:

a: !horse 2
b: !goat 1

then

yq '.a -= .b' sample.yml

will output

a: !horse 1
b: !goat 1

Tag

The tag operator can be used to get or set the tag of nodes (e.g. !!str, !!int, !!bool).

Get tag

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f: []

then

yq '.. | tag' sample.yml

will output

!!map
!!str
!!int
!!float
!!bool
!!seq

type is an alias for tag

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true
f: []

then

yq '.. | type' sample.yml

will output

!!map
!!str
!!int
!!float
!!bool
!!seq

Set custom tag

Given a sample.yml file of:

a: str

then

yq '.a tag = "!!mikefarah"' sample.yml

will output

a: !!mikefarah str

Find numbers and convert them to strings

Given a sample.yml file of:

a: cat
b: 5
c: 3.2
e: true

then

yq '(.. | select(tag == "!!int")) tag= "!!str"' sample.yml

will output

a: cat
b: "5"
c: 3.2
e: true

To Number

Parses the input as a number. yq will try to parse values as an int first, failing that it will try float. Values that already ints or floats will be left alone.

Converts strings to numbers

Given a sample.yml file of:

- "3"
- "3.1"
- "-1e3"

then

yq '.[] | to_number' sample.yml

will output

3
3.1
-1e3

Doesn’t change numbers

Given a sample.yml file of:

- 3
- 3.1
- -1e3

then

yq '.[] | to_number' sample.yml

will output

3
3.1
-1e3

Cannot convert null

Running

yq --null-input '.a.b | to_number'

will output

Error: cannot convert node value [null] at path a.b of tag !!null to number

Traverse (Read)

This is the simplest (and perhaps most used) operator. It is used to navigate deeply into yaml structures.

Simple map navigation

Given a sample.yml file of:

a:
  b: apple

then

yq '.a' sample.yml

will output

b: apple

Splat

Often used to pipe children into other operators

Given a sample.yml file of:

- b: apple
- c: banana

then

yq '.[]' sample.yml

will output

b: apple
c: banana

Optional Splat

Just like splat, but won’t error if you run it against scalars

Given a sample.yml file of:

cat

then

yq '.[]' sample.yml

will output

Special characters

Use quotes with square brackets around path elements with special characters

Given a sample.yml file of:

"{}": frog

then

yq '.["{}"]' sample.yml

will output

frog

Nested special characters

Given a sample.yml file of:

a:
  "key.withdots":
    "another.key": apple

then

yq '.a["key.withdots"]["another.key"]' sample.yml

will output

apple

Keys with spaces

Use quotes with square brackets around path elements with special characters

Given a sample.yml file of:

"red rabbit": frog

then

yq '.["red rabbit"]' sample.yml

will output

frog

Dynamic keys

Expressions within [] can be used to dynamically lookup / calculate keys

Given a sample.yml file of:

b: apple
apple: crispy yum
banana: soft yum

then

yq '.[.b]' sample.yml

will output

crispy yum

Children don’t exist

Nodes are added dynamically while traversing

Given a sample.yml file of:

c: banana

then

yq '.a.b' sample.yml

will output

null

Optional identifier

Like jq, does not output an error when the yaml is not an array or object as expected

Given a sample.yml file of:

- 1
- 2
- 3

then

yq '.a?' sample.yml

will output

Wildcard matching

Given a sample.yml file of:

a:
  cat: apple
  mad: things

then

yq '.a."*a*"' sample.yml

will output

apple
things

Aliases

Given a sample.yml file of:

a: &cat
  c: frog
b: *cat

then

yq '.b' sample.yml

will output

*cat

Traversing aliases with splat

Given a sample.yml file of:

a: &cat
  c: frog
b: *cat

then

yq '.b[]' sample.yml

will output

frog

Traversing aliases explicitly

Given a sample.yml file of:

a: &cat
  c: frog
b: *cat

then

yq '.b.c' sample.yml

will output

frog

Traversing arrays by index

Given a sample.yml file of:

- 1
- 2
- 3

then

yq '.[0]' sample.yml

will output

1

Traversing nested arrays by index

Given a sample.yml file of:

[[], [cat]]

then

yq '.[1][0]' sample.yml

will output

cat

Maps with numeric keys

Given a sample.yml file of:

2: cat

then

yq '.[2]' sample.yml

will output

cat

Maps with non existing numeric keys

Given a sample.yml file of:

a: b

then

yq '.[0]' sample.yml

will output

null

Traversing merge anchors

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar.a' sample.yml

will output

foo_a

Traversing merge anchors with override

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar.c' sample.yml

will output

foo_c

Traversing merge anchors with local override

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar.thing' sample.yml

will output

foobar_thing

Splatting merge anchors

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobar[]' sample.yml

will output

foo_c
foo_a
foobar_thing

Traversing merge anchor lists

Note that the later merge anchors override previous

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobarList.thing' sample.yml

will output

bar_thing

Splatting merge anchor lists

Given a sample.yml file of:

foo: &foo
  a: foo_a
  thing: foo_thing
  c: foo_c
bar: &bar
  b: bar_b
  thing: bar_thing
  c: bar_c
foobarList:
  b: foobarList_b
  !!merge <<:
    - *foo
    - *bar
  c: foobarList_c
foobar:
  c: foobar_c
  !!merge <<: *foo
  thing: foobar_thing

then

yq '.foobarList[]' sample.yml

will output

bar_b
foo_a
bar_thing
foobarList_c

Select multiple indices

Given a sample.yml file of:

a:
  - a
  - b
  - c

then

yq '.a[0, 2]' sample.yml

will output

a
c

Union

This operator is used to combine different results together.

Combine scalars

Running

yq --null-input '1, true, "cat"'

will output

1
true
cat

Combine selected paths

Given a sample.yml file of:

a: fieldA
b: fieldB
c: fieldC

then

yq '.a, .c' sample.yml

will output

fieldA
fieldC

Unique

This is used to filter out duplicated items in an array. Note that the original order of the array is maintained.

Unique array of scalars (string/numbers)

Note that unique maintains the original order of the array.

Given a sample.yml file of:

- 2
- 1
- 3
- 2

then

yq 'unique' sample.yml

will output

- 2
- 1
- 3

Unique nulls

Unique works on the node value, so it considers different representations of nulls to be different

Given a sample.yml file of:

- ~
- null
- ~
- null

then

yq 'unique' sample.yml

will output

- ~
- null

Unique all nulls

Run against the node tag to unique all the nulls

Given a sample.yml file of:

- ~
- null
- ~
- null

then

yq 'unique_by(tag)' sample.yml

will output

- ~

Unique array objects

Given a sample.yml file of:

- name: harry
  pet: cat
- name: billy
  pet: dog
- name: harry
  pet: cat

then

yq 'unique' sample.yml

will output

- name: harry
  pet: cat
- name: billy
  pet: dog

Unique array of objects by a field

Given a sample.yml file of:

- name: harry
  pet: cat
- name: billy
  pet: dog
- name: harry
  pet: dog

then

yq 'unique_by(.name)' sample.yml

will output

- name: harry
  pet: cat
- name: billy
  pet: dog

Unique array of arrays

Given a sample.yml file of:

- - cat
  - dog
- - cat
  - sheep
- - cat
  - dog

then

yq 'unique' sample.yml

will output

- - cat
  - dog
- - cat
  - sheep

Variable Operators

Like the jq equivalents, variables are sometimes required for the more complex expressions (or swapping values between fields).

Note that there is also an additional ref operator that holds a reference (instead of a copy) of the path, allowing you to make multiple changes to the same path.

Single value variable

Given a sample.yml file of:

a: cat

then

yq '.a as $foo | $foo' sample.yml

will output

cat

Multi value variable

Given a sample.yml file of:

- cat
- dog

then

yq '.[] as $foo | $foo' sample.yml

will output

cat
dog

Using variables as a lookup

Example taken from jq

Given a sample.yml file of:

"posts":
  - "title": First post
    "author": anon
  - "title": A well-written article
    "author": person1
"realnames":
  "anon": Anonymous Coward
  "person1": Person McPherson

then

yq '.realnames as $names | .posts[] | {"title":.title, "author": $names[.author]}' sample.yml

will output

title: First post
author: Anonymous Coward
title: A well-written article
author: Person McPherson

Using variables to swap values

Given a sample.yml file of:

a: a_value
b: b_value

then

yq '.a as $x  | .b as $y | .b = $x | .a = $y' sample.yml

will output

a: b_value
b: a_value

Use ref to reference a path repeatedly

Note: You may find the with operator more useful.

Given a sample.yml file of:

a:
  b: thing
  c: something

then

yq '.a.b ref $x | $x = "new" | $x style="double"' sample.yml

will output

a:
  b: "new"
  c: something

With

Use the with operator to conveniently make multiple updates to a deeply nested path, or to update array elements relatively to each other. The first argument expression sets the root context, and the second expression runs against that root context.

Update and style

Given a sample.yml file of:

a:
  deeply:
    nested: value

then

yq 'with(.a.deeply.nested; . = "newValue" | . style="single")' sample.yml

will output

a:
  deeply:
    nested: 'newValue'

Update multiple deeply nested properties

Given a sample.yml file of:

a:
  deeply:
    nested: value
    other: thing

then

yq 'with(.a.deeply; .nested = "newValue" | .other= "newThing")' sample.yml

will output

a:
  deeply:
    nested: newValue
    other: newThing

Update array elements relatively

The second expression runs with each element of the array as it’s contextual root. This allows you to make updates relative to the element.

Given a sample.yml file of:

myArray:
  - a: apple
  - a: banana

then

yq 'with(.myArray[]; .b = .a + " yum")' sample.yml

will output

myArray:
  - a: apple
    b: apple yum
  - a: banana
    b: banana yum

USAGE

Output format

These flags are available for all yq commands.

Color

By default, yq prints with colours if it detects a terminal. You can manually change this by using either

The --colors/-C flag to force print with colors.

The --no-colors/-M flag to force print without colours

Pretty Print

To print out idiomatic yaml use the --prettyPrint/-P flag. Note that this is shorthand for using the style operator ... style=""

Indent

Use the indent flag --indent/-I to control the number of spaces used for indentation. This also works for JSON output. The default value is 2.

Note that lists are indented at the same level as the map key at indent level 2, but are more deeply indented at indent level 4 and greater. This is (currently) a quirk of the underlying yaml parser.

Given:

apples:
  collection:
  - name: Green
  - name: Blue
  favourite: Pink Lady

Then:

yq -I4 sample.yaml

Will print out:

apples:
    collection:
      - name: Green
      - name: Blue
    favourite: Pink Lady

This also works with json

yq -j -I4 sample.yaml

yields

{
    "apples": {
        "collection": [
            {
                "name": "Green"
            },
            {
                "name": "Blue"
            }
        ],
        "favourite": "Pink Lady"
    }
}

Unwrap scalars

By default scalar values are ‘unwrapped’, that is only their value is printed (except when outputting as JSON). To print out the node as-is, with the original formatting an any comments pass in --unwrapScalar=false

Given data.yml:

a: "Things" # cool stuff

Then:

yq --unwrapScalar=false '.a' data.yml

Will yield:

"Things" # cool stuff

where as without setting the flag to false you would get:

Things

Working with CSV, TSV

Encode/Decode/Roundtrip CSV and TSV files.

Encode

Currently supports arrays of homogeneous flat objects, that is: no nesting and it assumes the first object has all the keys required:

- name: Bobo
  type: dog
- name: Fifi
  type: cat

As well as arrays of arrays of scalars (strings/numbers/booleans):

- [Bobo, dog]
- [Fifi, cat]

Decode

Decode assumes the first CSV/TSV row is the header row, and all rows beneath are the entries. The data will be coded into an array of objects, using the header rows as keys.

name,type
Bobo,dog
Fifi,cat

Encode CSV simple

Given a sample.yml file of:

- [i, like, csv]
- [because, excel, is, cool]

then

yq -o=csv sample.yml

will output

i,like,csv
because,excel,is,cool

Encode TSV simple

Given a sample.yml file of:

- [i, like, csv]
- [because, excel, is, cool]

then

yq -o=tsv sample.yml

will output

i	like	csv
because	excel	is	cool

Encode array of objects to csv

Given a sample.yml file of:

- name: Gary
  numberOfCats: 1
  likesApples: true
  height: 168.8
- name: Samantha's Rabbit
  numberOfCats: 2
  likesApples: false
  height: -188.8

then

yq -o=csv sample.yml

will output

name,numberOfCats,likesApples,height
Gary,1,true,168.8
Samantha's Rabbit,2,false,-188.8

Encode array of objects to custom csv format

Add the header row manually, then the we convert each object into an array of values - resulting in an array of arrays. Pick the columns and call the header whatever you like.

Given a sample.yml file of:

- name: Gary
  numberOfCats: 1
  likesApples: true
  height: 168.8
- name: Samantha's Rabbit
  numberOfCats: 2
  likesApples: false
  height: -188.8

then

yq -o=csv '[["Name", "Number of Cats"]] +  [.[] | [.name, .numberOfCats ]]' sample.yml

will output

Name,Number of Cats
Gary,1
Samantha's Rabbit,2

Encode array of objects to csv - missing fields behaviour

First entry is used to determine the headers, and it is missing ’likesApples’, so it is not included in the csv. Second entry does not have ’numberOfCats’ so that is blank

Given a sample.yml file of:

- name: Gary
  numberOfCats: 1
  height: 168.8
- name: Samantha's Rabbit
  height: -188.8
  likesApples: false

then

yq -o=csv sample.yml

will output

name,numberOfCats,height
Gary,1,168.8
Samantha's Rabbit,,-188.8

Parse CSV into an array of objects

First row is assumed to be the header row. By default, entries with YAML/JSON formatting will be parsed!

Given a sample.csv file of:

name,numberOfCats,likesApples,height,facts
Gary,1,true,168.8,cool: true
Samantha's Rabbit,2,false,-188.8,tall: indeed

then

yq -p=csv sample.csv

will output

- name: Gary
  numberOfCats: 1
  likesApples: true
  height: 168.8
  facts:
    cool: true
- name: Samantha's Rabbit
  numberOfCats: 2
  likesApples: false
  height: -188.8
  facts:
    tall: indeed

Parse CSV into an array of objects, no auto-parsing

First row is assumed to be the header row. Entries with YAML/JSON will be left as strings.

Given a sample.csv file of:

name,numberOfCats,likesApples,height,facts
Gary,1,true,168.8,cool: true
Samantha's Rabbit,2,false,-188.8,tall: indeed

then

yq -p=csv --csv-auto-parse=f sample.csv

will output

- name: Gary
  numberOfCats: 1
  likesApples: true
  height: 168.8
  facts: 'cool: true'
- name: Samantha's Rabbit
  numberOfCats: 2
  likesApples: false
  height: -188.8
  facts: 'tall: indeed'

Parse TSV into an array of objects

First row is assumed to be the header row.

Given a sample.tsv file of:

name	numberOfCats	likesApples	height
Gary	1	true	168.8
Samantha's Rabbit	2	false	-188.8

then

yq -p=tsv sample.tsv

will output

- name: Gary
  numberOfCats: 1
  likesApples: true
  height: 168.8
- name: Samantha's Rabbit
  numberOfCats: 2
  likesApples: false
  height: -188.8

Round trip

Given a sample.csv file of:

name,numberOfCats,likesApples,height
Gary,1,true,168.8
Samantha's Rabbit,2,false,-188.8

then

yq -p=csv -o=csv '(.[] | select(.name == "Gary") | .numberOfCats) = 3' sample.csv

will output

name,numberOfCats,likesApples,height
Gary,3,true,168.8
Samantha's Rabbit,2,false,-188.8

Working with JSON

Encode and decode to and from JSON. Supports multiple JSON documents in a single file (e.g. NDJSON).

Note that YAML is a superset of (single document) JSON - so you don’t have to use the JSON parser to read JSON when there is only one JSON document in the input. You will probably want to pretty print the result in this case, to get idiomatic YAML styling.

Parse json: simple

JSON is a subset of yaml, so all you need to do is prettify the output

Given a sample.json file of:

{"cat": "meow"}

then

yq -p=json sample.json

will output

cat: meow

Parse json: complex

JSON is a subset of yaml, so all you need to do is prettify the output

Given a sample.json file of:

{"a":"Easy! as one two three","b":{"c":2,"d":[3,4]}}

then

yq -p=json sample.json

will output

a: Easy! as one two three
b:
  c: 2
  d:
    - 3
    - 4

Encode json: simple

Given a sample.yml file of:

cat: meow

then

yq -o=json '.' sample.yml

will output

{
  "cat": "meow"
}

Encode json: simple - in one line

Given a sample.yml file of:

cat: meow # this is a comment, and it will be dropped.

then

yq -o=json -I=0 '.' sample.yml

will output

{"cat":"meow"}

Encode json: comments

Given a sample.yml file of:

cat: meow # this is a comment, and it will be dropped.

then

yq -o=json '.' sample.yml

will output

{
  "cat": "meow"
}

Encode json: anchors

Anchors are dereferenced

Given a sample.yml file of:

cat: &ref meow
anotherCat: *ref

then

yq -o=json '.' sample.yml

will output

{
  "cat": "meow",
  "anotherCat": "meow"
}

Encode json: multiple results

Each matching node is converted into a json doc. This is best used with 0 indent (json document per line)

Given a sample.yml file of:

things: [{stuff: cool}, {whatever: cat}]

then

yq -o=json -I=0 '.things[]' sample.yml

will output

{"stuff":"cool"}
{"whatever":"cat"}

Roundtrip JSON Lines / NDJSON

Given a sample.json file of:

{"this": "is a multidoc json file"}
{"each": ["line is a valid json document"]}
{"a number": 4}

then

yq -p=json -o=json -I=0 sample.json

will output

{"this":"is a multidoc json file"}
{"each":["line is a valid json document"]}
{"a number":4}

Roundtrip multi-document JSON

The parser can also handle multiple multi-line json documents in a single file (despite this not being in the JSON Lines / NDJSON spec). Typically you would have one entire JSON document per line, but the parser also supports multiple multi-line json documents

Given a sample.json file of:

{
	"this": "is a multidoc json file"
}
{
	"it": [
		"has",
		"consecutive",
		"json documents"
	]
}
{
	"a number": 4
}

then

yq -p=json -o=json -I=2 sample.json

will output

{
  "this": "is a multidoc json file"
}
{
  "it": [
    "has",
    "consecutive",
    "json documents"
  ]
}
{
  "a number": 4
}

Update a specific document in a multi-document json

Documents are indexed by the documentIndex or di operator.

Given a sample.json file of:

{"this": "is a multidoc json file"}
{"each": ["line is a valid json document"]}
{"a number": 4}

then

yq -p=json -o=json -I=0 '(select(di == 1) | .each ) += "cool"' sample.json

will output

{"this":"is a multidoc json file"}
{"each":["line is a valid json document","cool"]}
{"a number":4}

Find and update a specific document in a multi-document json

Use expressions as you normally would.

Given a sample.json file of:

{"this": "is a multidoc json file"}
{"each": ["line is a valid json document"]}
{"a number": 4}

then

yq -p=json -o=json -I=0 '(select(has("each")) | .each ) += "cool"' sample.json

will output

{"this":"is a multidoc json file"}
{"each":["line is a valid json document","cool"]}
{"a number":4}

Decode JSON Lines / NDJSON

Given a sample.json file of:

{"this": "is a multidoc json file"}
{"each": ["line is a valid json document"]}
{"a number": 4}

then

yq -p=json sample.json

will output

this: is a multidoc json file
---
each:
  - line is a valid json document
---
a number: 4

Working with Properties

Encode/Decode/Roundtrip to/from a property file. Line comments on value nodes will be copied across.

By default, empty maps and arrays are not encoded - see below for an example on how to encode a value for these.

Encode properties

Note that empty arrays and maps are not encoded by default.

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props sample.yml

will output

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets.0 = cat
person.pets.1.nested.0 = list entry
person.food.0 = pizza

Encode properties with array brackets

Declare the –properties-array-brackets flag to give array paths in brackets (e.g. SpringBoot).

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props --properties-array-brackets sample.yml

will output

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets[0] = cat
person.pets[1].nested[0] = list entry
person.food[0] = pizza

Encode properties - custom separator

Use the –properties-separator flag to specify your own key/value separator.

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props --properties-separator=" :@ " sample.yml

will output

# block comments come through
# comments on values appear
person.name :@ Mike Wazowski

# comments on array values appear
person.pets.0 :@ cat
person.pets.1.nested.0 :@ list entry
person.food.0 :@ pizza

Encode properties: scalar encapsulation

Note that string values with blank characters in them are encapsulated with double quotes

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props --unwrapScalar=false sample.yml

will output

# block comments come through
# comments on values appear
person.name = "Mike Wazowski"

# comments on array values appear
person.pets.0 = cat
person.pets.1.nested.0 = "list entry"
person.food.0 = pizza

Encode properties: no comments

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props '... comments = ""' sample.yml

will output

person.name = Mike Wazowski
person.pets.0 = cat
person.pets.1.nested.0 = list entry
person.food.0 = pizza

Encode properties: include empty maps and arrays

Use a yq expression to set the empty maps and sequences to your desired value.

Given a sample.yml file of:

# block comments come through
person: # neither do comments on maps
    name: Mike Wazowski # comments on values appear
    pets: 
    - cat # comments on array values appear
    - nested:
        - list entry
    food: [pizza] # comments on arrays do not
emptyArray: []
emptyMap: []

then

yq -o=props '(.. | select( (tag == "!!map" or tag =="!!seq") and length == 0)) = ""' sample.yml

will output

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets.0 = cat
person.pets.1.nested.0 = list entry
person.food.0 = pizza
emptyArray = 
emptyMap = 

Decode properties

Given a sample.properties file of:

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets.0 = cat
person.pets.1.nested.0 = list entry
person.food.0 = pizza

then

yq -p=props sample.properties

will output

person:
  # block comments come through
  # comments on values appear
  name: Mike Wazowski
  pets:
    # comments on array values appear
    - cat
    - nested:
        - list entry
  food:
    - pizza

Decode properties: numbers

All values are assumed to be strings when parsing properties, but you can use the from_yaml operator on all the strings values to autoparse into the correct type.

Given a sample.properties file of:

a.b = 10

then

yq -p=props ' (.. | select(tag == "!!str")) |= from_yaml' sample.properties

will output

a:
  b: 10

Decode properties - array should be a map

If you have a numeric map key in your property files, use array_to_map to convert them to maps.

Given a sample.properties file of:

things.10 = mike

then

yq -p=props '.things |= array_to_map' sample.properties

will output

things:
  10: mike

Roundtrip

Given a sample.properties file of:

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets.0 = cat
person.pets.1.nested.0 = list entry
person.food.0 = pizza

then

yq -p=props -o=props '.person.pets.0 = "dog"' sample.properties

will output

# block comments come through
# comments on values appear
person.name = Mike Wazowski

# comments on array values appear
person.pets.0 = dog
person.pets.1.nested.0 = list entry
person.food.0 = pizza

Working with XML

Encode and decode to and from XML. Whitespace is not conserved for round trips - but the order of the fields are.

Consecutive xml nodes with the same name are assumed to be arrays.

XML content data, attributes processing instructions and directives are all created as plain fields.

This can be controlled by:

Flag Default Sample XML
--xml-attribute-prefix + (changing to +@ soon) Legs in <cat legs="4"/>
--xml-content-name +content Meow in <cat>Meow <fur>true</true></cat>
--xml-directive-name +directive <!DOCTYPE config system "blah">
--xml-proc-inst-prefix +p_ <?xml version="1"?>

{% hint style=“warning” %} Default Attribute Prefix will be changing in v4.30! In order to avoid name conflicts (e.g. having an attribute named “content” will create a field that clashes with the default content name of “+content”) the attribute prefix will be changing to “+@”.

This will affect users that have not set their own prefix and are not roundtripping XML changes.

{% endhint %}

Encoder / Decoder flag options

In addition to the above flags, there are the following xml encoder/decoder options controlled by flags:

Flag Default Description
--xml-strict-mode false Strict mode enforces the requirements of the XML specification. When switched off the parser allows input containing common mistakes. See the Golang xml decoder for more details.
--xml-keep-namespace true Keeps the namespace of attributes
--xml-raw-token true Does not verify that start and end elements match and does not translate name space prefixes to their corresponding URLs.
--xml-skip-proc-inst false Skips over processing instructions, e.g. <?xml version="1"?>
--xml-skip-directives false Skips over directives, e.g. <!DOCTYPE config system "blah">

See below for examples

Parse xml: simple

Notice how all the values are strings, see the next example on how you can fix that.

Given a sample.xml file of:

<?xml version="1.0" encoding="UTF-8"?>
<cat>
  <says>meow</says>
  <legs>4</legs>
  <cute>true</cute>
</cat>

then

yq -oy '.' sample.xml

will output

+p_xml: version="1.0" encoding="UTF-8"
cat:
  says: meow
  legs: "4"
  cute: "true"

Parse xml: number

All values are assumed to be strings when parsing XML, but you can use the from_yaml operator on all the strings values to autoparse into the correct type.

Given a sample.xml file of:

<?xml version="1.0" encoding="UTF-8"?>
<cat>
  <says>meow</says>
  <legs>4</legs>
  <cute>true</cute>
</cat>

then

yq -oy ' (.. | select(tag == "!!str")) |= from_yaml' sample.xml

will output

+p_xml: version="1.0" encoding="UTF-8"
cat:
  says: meow
  legs: 4
  cute: true

Parse xml: array

Consecutive nodes with identical xml names are assumed to be arrays.

Given a sample.xml file of:

<?xml version="1.0" encoding="UTF-8"?>
<animal>cat</animal>
<animal>goat</animal>

then

yq -oy '.' sample.xml

will output

+p_xml: version="1.0" encoding="UTF-8"
animal:
  - cat
  - goat

Parse xml: force as an array

In XML, if your array has a single item, then yq doesn’t know its an array. This is how you can consistently force it to be an array. This handles the 3 scenarios of having nothing in the array, having a single item and having multiple.

Given a sample.xml file of:

<zoo><animal>cat</animal></zoo>

then

yq -oy '.zoo.animal |= ([] + .)' sample.xml

will output

zoo:
  animal:
    - cat

Parse xml: force all as an array

Given a sample.xml file of:

<zoo><thing><frog>boing</frog></thing></zoo>

then

yq -oy '.. |= [] + .' sample.xml

will output

- zoo:
    - thing:
        - frog:
            - boing

Parse xml: attributes

Attributes are converted to fields, with the default attribute prefix ‘+’. Use ‘–xml-attribute-prefix` to set your own.

Given a sample.xml file of:

<?xml version="1.0" encoding="UTF-8"?>
<cat legs="4">
  <legs>7</legs>
</cat>

then

yq -oy '.' sample.xml

will output

+p_xml: version="1.0" encoding="UTF-8"
cat:
  +@legs: "4"
  legs: "7"

Parse xml: attributes with content

Content is added as a field, using the default content name of +content. Use --xml-content-name to set your own.

Given a sample.xml file of:

<?xml version="1.0" encoding="UTF-8"?>
<cat legs="4">meow</cat>

then

yq -oy '.' sample.xml

will output

+p_xml: version="1.0" encoding="UTF-8"
cat:
  +content: meow
  +@legs: "4"

Parse xml: content split between comments/children

Multiple content texts are collected into a sequence.

Given a sample.xml file of:

<root>  value  <!-- comment-->anotherValue <a>frog</a> cool!</root>

then

yq -oy '.' sample.xml

will output

root:
  +content: # comment
    - value
    - anotherValue
    - cool!
  a: frog

Parse xml: custom dtd

DTD entities are processed as directives.

Given a sample.xml file of:


<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY writer "Blah.">
<!ENTITY copyright "Blah">
]>
<root>
    <item>&writer;&copyright;</item>
</root>

then

yq '.' sample.xml

will output

<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY writer "Blah.">
<!ENTITY copyright "Blah">
]>
<root>
  <item>&amp;writer;&amp;copyright;</item>
</root>

Parse xml: skip custom dtd

DTDs are directives, skip over directives to skip DTDs.

Given a sample.xml file of:


<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY writer "Blah.">
<!ENTITY copyright "Blah">
]>
<root>
    <item>&writer;&copyright;</item>
</root>

then

yq --xml-skip-directives '.' sample.xml

will output

<?xml version="1.0"?>
<root>
  <item>&amp;writer;&amp;copyright;</item>
</root>

Parse xml: with comments

A best attempt is made to preserve comments.

Given a sample.xml file of:


<!-- before cat -->
<cat>
	<!-- in cat before -->
	<x>3<!-- multi
line comment 
for x --></x>
	<!-- before y -->
	<y>
		<!-- in y before -->
		<d><!-- in d before -->z<!-- in d after --></d>
		
		<!-- in y after -->
	</y>
	<!-- in_cat_after -->
</cat>
<!-- after cat -->

then

yq -oy '.' sample.xml

will output

# before cat
cat:
  # in cat before
  x: "3" # multi
  # line comment 
  # for x
  # before y

  y:
    # in y before
    # in d before
    d: z # in d after
    # in y after
  # in_cat_after
# after cat

Parse xml: keep attribute namespace

Defaults to true

Given a sample.xml file of:

<?xml version="1.0"?>
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url"></map>

then

yq --xml-keep-namespace=false '.' sample.xml

will output

<?xml version="1.0"?>
<map xmlns="some-namespace" xsi="some-instance" schemaLocation="some-url"></map>

instead of

<?xml version="1.0"?>
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url"></map>

Parse xml: keep raw attribute namespace

Defaults to true

Given a sample.xml file of:

<?xml version="1.0"?>
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url"></map>

then

yq --xml-raw-token=false '.' sample.xml

will output

<?xml version="1.0"?>
<map xmlns="some-namespace" xmlns:xsi="some-instance" some-instance:schemaLocation="some-url"></map>

instead of

<?xml version="1.0"?>
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url"></map>

Encode xml: simple

Given a sample.yml file of:

cat: purrs

then

yq -o=xml sample.yml

will output

<cat>purrs</cat>

Encode xml: array

Given a sample.yml file of:

pets:
  cat:
    - purrs
    - meows

then

yq -o=xml sample.yml

will output

<pets>
  <cat>purrs</cat>
  <cat>meows</cat>
</pets>

Encode xml: attributes

Fields with the matching xml-attribute-prefix are assumed to be attributes.

Given a sample.yml file of:

cat:
  +@name: tiger
  meows: true

then

yq -o=xml sample.yml

will output

<cat name="tiger">
  <meows>true</meows>
</cat>

Encode xml: attributes with content

Fields with the matching xml-content-name is assumed to be content.

Given a sample.yml file of:

cat:
  +@name: tiger
  +content: cool

then

yq -o=xml sample.yml

will output

<cat name="tiger">cool</cat>

Encode xml: comments

A best attempt is made to copy comments to xml.

Given a sample.yml file of:

#
# header comment
# above_cat
#
cat: # inline_cat
  # above_array
  array: # inline_array
    - val1 # inline_val1
    # above_val2
    - val2 # inline_val2
# below_cat

then

yq -o=xml sample.yml

will output

<!--
header comment
above_cat
-->
<!-- inline_cat -->
<cat><!-- above_array inline_array -->
  <array>val1<!-- inline_val1 --></array>
  <array><!-- above_val2 -->val2<!-- inline_val2 --></array>
</cat><!-- below_cat -->

Encode: doctype and xml declaration

Use the special xml names to add/modify proc instructions and directives.

Given a sample.yml file of:

+p_xml: version="1.0"
+directive: 'DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" '
apple:
  +p_coolioo: version="1.0"
  +directive: 'CATYPE meow purr puss '
  b: things

then

yq -o=xml sample.yml

will output

<?xml version="1.0"?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
<apple><?coolioo version="1.0"?><!CATYPE meow purr puss >
  <b>things</b>
</apple>

Round trip: with comments

A best effort is made, but comment positions and white space are not preserved perfectly.

Given a sample.xml file of:


<!-- before cat -->
<cat>
	<!-- in cat before -->
	<x>3<!-- multi
line comment 
for x --></x>
	<!-- before y -->
	<y>
		<!-- in y before -->
		<d><!-- in d before -->z<!-- in d after --></d>
		
		<!-- in y after -->
	</y>
	<!-- in_cat_after -->
</cat>
<!-- after cat -->

then

yq '.' sample.xml

will output

<!-- before cat -->
<cat><!-- in cat before -->
  <x>3<!-- multi
line comment 
for x --></x><!-- before y -->
  <y><!-- in y before
in d before -->
    <d>z<!-- in d after --></d><!-- in y after -->
  </y><!-- in_cat_after -->
</cat><!-- after cat -->

Roundtrip: with doctype and declaration

yq parses XML proc instructions and directives into nodes. Unfortunately the underlying XML parser loses whitespace information.

Given a sample.xml file of:

<?xml version="1.0"?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
<apple>
  <?coolioo version="1.0"?>
  <!CATYPE meow purr puss >
  <b>things</b>
</apple>

then

yq '.' sample.xml

will output

<?xml version="1.0"?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
<apple><?coolioo version="1.0"?><!CATYPE meow purr puss >
  <b>things</b>
</apple>

Working with LUA

Basic input example

Given a sample.lua file of:

return {
	["country"] = "Australia"; -- this place
	["cities"] = {
		"Sydney",
		"Melbourne",
		"Brisbane",
		"Perth",
	};
};

then

yq -oy '.' sample.lua

will output

country: Australia
cities:
  - Sydney
  - Melbourne
  - Brisbane
  - Perth

Basic output example

Given a sample.yml file of:

---
country: Australia # this place
cities:
- Sydney
- Melbourne
- Brisbane
- Perth

then

yq -o=lua '.' sample.yml

will output

return {
	["country"] = "Australia"; -- this place
	["cities"] = {
		"Sydney",
		"Melbourne",
		"Brisbane",
		"Perth",
	};
};

Unquoted keys

Uses the --lua-unquoted option to produce a nicer-looking output.

Given a sample.yml file of:

---
country: Australia # this place
cities:
- Sydney
- Melbourne
- Brisbane
- Perth

then

yq -o=lua --lua-unquoted '.' sample.yml

will output

return {
	country = "Australia"; -- this place
	cities = {
		"Sydney",
		"Melbourne",
		"Brisbane",
		"Perth",
	};
};

Globals

Uses the --lua-globals option to export the values into the global scope.

Given a sample.yml file of:

---
country: Australia # this place
cities:
- Sydney
- Melbourne
- Brisbane
- Perth

then

yq -o=lua --lua-globals '.' sample.yml

will output

country = "Australia"; -- this place
cities = {
	"Sydney",
	"Melbourne",
	"Brisbane",
	"Perth",
};

Elaborate example

Given a sample.yml file of:

---
hello: world
tables:
  like: this
  keys: values
  ? look: non-string keys
  : True
numbers:
  - decimal: 12345
  - hex: 0x7fabc123
  - octal: 0o30
  - float: 123.45
  - infinity: .inf
    plus_infinity: +.inf
    minus_infinity: -.inf
  - not: .nan

then

yq -o=lua '.' sample.yml

will output

return {
	["hello"] = "world";
	["tables"] = {
		["like"] = "this";
		["keys"] = "values";
		[{
			["look"] = "non-string keys";
		}] = true;
	};
	["numbers"] = {
		{
			["decimal"] = 12345;
		},
		{
			["hex"] = 0x7fabc123;
		},
		{
			["octal"] = 24;
		},
		{
			["float"] = 123.45;
		},
		{
			["infinity"] = (1/0);
			["plus_infinity"] = (1/0);
			["minus_infinity"] = (-1/0);
		},
		{
			["not"] = (0/0);
		},
	};
};

Working with TOML

Decode from TOML. Note that yq does not yet support outputting in TOML format (and therefore it cannot roundtrip)

Parse: Simple

Given a sample.toml file of:

A = "hello"
B = 12

then

yq -oy '.' sample.toml

will output

A: hello
B: 12

Parse: Deep paths

Given a sample.toml file of:

person.name = "hello"
person.address = "12 cat st"

then

yq -oy '.' sample.toml

will output

person:
  name: hello
  address: 12 cat st

Encode: Scalar

Given a sample.toml file of:

person.name = "hello"
person.address = "12 cat st"

then

yq '.person.name' sample.toml

will output

hello

Parse: inline table

Given a sample.toml file of:

name = { first = "Tom", last = "Preston-Werner" }

then

yq -oy '.' sample.toml

will output

name:
  first: Tom
  last: Preston-Werner

Parse: Array Table

Given a sample.toml file of:


[owner.contact]
name = "Tom Preston-Werner"
age = 36

[[owner.addresses]]
street = "first street"
suburb = "ok"

[[owner.addresses]]
street = "second street"
suburb = "nice"

then

yq -oy '.' sample.toml

will output

owner:
  contact:
    name: Tom Preston-Werner
    age: 36
  addresses:
    - street: first street
      suburb: ok
    - street: second street
      suburb: nice

Parse: Empty Table

Given a sample.toml file of:


[dependencies]

then

yq -oy '.' sample.toml

will output

dependencies: {}

Working with Shell Output

Encode shell variables

Note that comments are dropped and values will be enclosed in single quotes as needed.

Given a sample.yml file of:

# comment
name: Mike Wazowski
eyes:
  color: turquoise
  number: 1
friends:
  - James P. Sullivan
  - Celia Mae

then

yq -o=shell sample.yml

will output

name='Mike Wazowski'
eyes_color=turquoise
eyes_number=1
friends_0='James P. Sullivan'
friends_1='Celia Mae'

Encode shell variables: illegal variable names as key.

Keys that would be illegal as variable keys are adapted.

Given a sample.yml file of:

ascii_=_symbols: replaced with _
"ascii_	_controls": dropped (this example uses \t)
nonascii_א_characters: dropped
effort_expeñded_tò_preserve_accented_latin_letters: moderate (via unicode NFKD)

then

yq -o=shell sample.yml

will output

ascii___symbols='replaced with _'
ascii__controls='dropped (this example uses \t)'
nonascii__characters=dropped
effort_expended_to_preserve_accented_latin_letters='moderate (via unicode NFKD)'

Encode shell variables: empty values, arrays and maps

Empty values are encoded to empty variables, but empty arrays and maps are skipped.

Given a sample.yml file of:

empty:
  value:
  array: []
  map:   {}

then

yq -o=shell sample.yml

will output

empty_value=

Encode shell variables: single quotes in values

Single quotes in values are encoded as ‘"’"’ (close single quote, double-quoted single quote, open single quote).

Given a sample.yml file of:

name: Miles O'Brien

then

yq -o=shell sample.yml

will output

name='Miles O'"'"'Brien'

Front Matter

yq can process files with yaml front matter (e.g. jekyll, assemble and others) - this is done via the --front-matter/-f flag.

Note that yq only processes the first passed in file for front-matter. If you’d like to process multiple files, you can:

find -name  "*.md" -exec yq --front-matter="process" '.updated_at = now' {} \;

Process front matter

Use --front-matter=process to process the front matter, that is run the expression against the yaml content, and output back the entire file, included the non-yaml content block. For example:

File:

---
a: apple
b: bannana
---
<h1>I like {{a}} and {{b}} </h1>

The running

yq --front-matter=process '.a="chocolate"' file.jekyll

Will yield:

---
a: chocolate
b: bannana
---
<h1>I like {{a}} and {{b}} </h1>

Extract front matter

Running with --front-matter=extract will only output the yaml contents and ignore the rest. From the previous example, if you were to instead run:

yq --front-matter=extract '.a="chocolate"' file.jekyll

Then this would yield:

---
a: chocolate
b: bannana

Split into multiple files

yq can split out the results into multiple files with the --split-exp/s flag. You will need to give this flag an expression (that returns a string), this will be used as the filename for each result. In this expression, you can use $index to represent the result index in the name, if desired.

Split documents into files

Given a file like

a: test_doc1
--- 
a: test_doc2

Then running:

yq -s '.a' myfile.yml

will result in two files:

test_doc1.yml:

a: test_doc1

test_doc2.yml:

---
a: test_doc2

TIP: if you don’t want the leading document separators (---), then run with the --no-doc flag.

Split documents into files, using index

This is like the example above, but we’ll use $index for the filename. Note that this variable is only defined for the --split-exp/s flag.

yq -s '"file_" + $index' myfile.yml

This will create two files, file_0.yml and file_1.yml.

Split single document into files

You can also split results into separate files. Notice

- name: bob
  age: 23
- name: tim
  age: 17

Then, by splatting the array into individual results, we can split the content into several files:

yq '.[]' file.yml -s '"user_" + .name'

will result in two files:

user_bob.yml:

name: bob
age: 23

user_tim.yml:

name: tim
age: 17

GitHub Action

Guide

You can use yq in your GitHub action, for instance:

  - uses: actions/checkout@v2
  - name: Get SDK Version from config
    id: lookupSdkVersion
    uses: mikefarah/yq@master
    with:
      cmd: yq '.renutil.version' 'config.yml'
  - name: Restore Cache
    id: restore-cache
    uses: actions/cache@v2
    with:
      path: ../renpy
      key:  ${{ runner.os }}-sdk-${{ steps.lookupSdkVersion.outputs.result }}
      restore-keys: |
        ${{ runner.os }}-sdk        
  # ... more

The yq action sets a result variable in its output, making it available to subsequent steps. In this case it’s available as steps.lookupSdkVersion.outputs.result.

Details of how the GitHub action itself is configured can be found here

If you enable step debug logging, you can see additional information about the exact command sent as well as the response returned within the GitHub Action logs.

Thanks @devorbitus!

Environment variables with Github Actions:

GitHub Actions escape and interpolate rules can conflict with some yq syntax. Here is an example of how to quote a variable that could contain dots in a query path (more usage context: ambanum/OpenTermsArchive#899).

  - name: Get an entry with a variable that might contain dots or spaces
    id: get_username
    uses: mikefarah/yq@master
    with:
      cmd: yq '.all.children.["${{ matrix.ip_address }}"].username' ops/inventories/production.yml
  - name: Reuse a variable obtained in another step
    run: echo ${{ steps.get_username.outputs.result }}

Thanks @MattiSG!

Troubleshooting

Write in-place file permission errors

The default user in github action dockerfiles (at the time of writing) seems to be 1001. This is what the yq github action is configured to run with (see the docker file here)

There’s a working example defined here and you can see the Github action results here

If you need to set the action to another user, follow the advice here.

Tips, Tricks, Troubleshooting

Validating yaml files

Yaml files can be surprisingly lenient in what can be parsed as a yaml file. A reasonable way of validation a yaml file is to ensure the top level is a map or array (although it is valid yaml to have scalars at the top level, but often this is not what you want). This can be done by:

yq --exit-status 'tag == "!!map" or tag== "!!seq"' file.txt > /dev/null

Split expressions over multiple lines to improve readability

Feel free to use multiple lines in your expression to improve readability.

Use with if you need to make several updates to the same path.

Use # comments to explain things

yq --inplace '
  with(.a.deeply.nested;
    . = "newValue" | . style="single" # line comment about styles
  ) |
  #
  # Block comment that explains what is happening.
  #
  with(.b.another.nested; 
    . = "cool" | . style="folded"
  )
' my_file.yaml

Create bash array

Given a yaml file like

coolActions:
  - create
  - edit
  - delete

You can create a bash array named actions by:

> readarray actions < <(yq '.coolActions[]' sample.yaml)
> echo "${actions[1]}"
edit

yq in a bash loop

For a given yaml file like:

identities:
- arn: "arn:aws:iam::ARN1"
  group: "system:masters"
  user: "user1"
- arn: "arn:aws:iam::ARN2"
  group: "system:masters"
  user: "user2"

You can loop over the results in a bash loop like:

# load array into a bash array
# output each entry as a single line json
readarray identityMappings < <(yq -o=j -I=0 '.identities[]' test.yml )

for identityMapping in "${identityMappings[@]}"; do
    # identity mapping is a single json snippet representing a single entry
    roleArn=$(echo "$identityMapping" | yq '.arn' -)
    echo "roleArn: $roleArn"
done

Set contents from another file

Use the load operator to load contents from another file.

Special characters in strings

The strenv operator is a great way to handle special characters in strings:

VAL='.a |!@  == "string2"' yq '.a = strenv(VAL)' example.yaml

Update multiple files

yq doesn’t have a way of updating multiple files in a single command (yet?) - but you can use your shell’s built in tools like find:

find *.yaml -exec yq '. += "cow"' -i {} \;

This will run the '. += "cow"' expression against every matching file, and update it in place (-i).

String blocks and newline issues

There are a couple of tricks to getting the right string representation, take a look at string operators for more details:

Quotes in Windows Powershell

Powershell has its own way of handling quotes:

PS > yq -n '.test = ""something""'
test: something
PS >

See https://github.com/mikefarah/yq/issues/747 for more trickery.

Merge / combine all documents into one

To merge all given yaml files into one, use the reduce operator with the * (multiply) operator. Note the use of ea or eval-all to load all files into memory so that they can be merged.

yq ea '. as $item ireduce ({}; . * $item )' file1.yml file2.yml ...

Merge - showing the source file and line

To see the original source file and line number of your merged result, you can pre-process the files and add that information in as line comments, then perform the merge.

yq ea '(..  lineComment |= filename + ":" + line) | select(fi==0) * select(fi==1)' data1.yaml data2.yaml

Merge an array of objects by key

See here for a working example.

Creating a new file / working with blank documents

To create a new yaml file simply:

yq -n '.someNew="content"' > newfile.yml

Comparing yaml files

The best way to run a diff is to use yq to normalise the yaml files and then just use diff. Here is a simple example of using pretty print -P to normalise the styling and running diff:

diff <(yq -P 'sort_keys(..)' -o=props file1.yaml) <(yq -P 'sort_keys(..)' -o=props file2.yaml)

This way you can use the full power of diff and normalise the yaml files as you like.

You may also want to remove all comments using ... comments=""

Reading multiple streams (STDINs)

Like diff and other bash commands, you can use <(exp) to pipe in multiple streams of data into yq. instance:

yq '.apple' <(curl -s https://somewhere/data1.yaml) <(cat file.yml)

Updating deeply selected paths

or why is yq only returning the updated yaml

The most important thing to remember to do is to have brackets around the LHS expression - otherwise what yq will do is first filter by the selection, and then, separately, update the filtered result and return that subset.

yq '(.foo.bar[] | select(.name == "fred") | .apple) = "cool"'

Combining multiple files into one

In order to combine multiple yaml files into a single file (with --- separators) you can just:

yq '.' somewhere/*.yaml

Multiple updates to the same path

You can use the with operator to set a nested context:

yq 'with(.a.deeply ; .nested = "newValue" | .other= "newThing")' sample.yml

The first argument expression sets the root context, and the second expression runs against that root context.

Logic without if/elif/else

yq has not yet added if expressions - however you should be able to use with and select to achieve the same outcome. Lets use an example:

- animal: cat
- animal: dog
- animal: frog

Now, if you were using good ol’ jq - you may have a script with ifs like so:

jq ' .[] |=
if (.animal == "cat") then
  .noise = "meow" |
  .whiskers = true
elif (.animal == "dog") then
  .noise = "woof" |
  .happy = true
else 
  .noise = "??"
end
' < file.yaml

Using yq - you can get the same result by:

yq '.[] |= (
  with(select(.animal == "cat"); 
    .noise = "meow" | 
    .whiskers = true
  ) |
  with(select(.animal == "dog"); 
    .noise = "woof" | 
    .happy = true
  ) |
  with(select(.noise == null); 
    .noise = "???"
  )
)' < file.yml

Note that the logic isn’t quite the same, as there is no concept of ’else’. So you may need to put additional logic in the expressions, as this has for the ’else’ logic.

yq adds a !!merge tag automatically

The merge functionality from yaml v1.1 (e.g. <<:has actually been removed in the 1.2 spec. Thankfully, yq underlying yaml parser still supports that tag - and it’s extra nice in that it explicitly puts the !!merge tag on key of the map entry. This tag tells other yaml parsers that this entry is a merge entry, as opposed to a regular string key that happens to have a value of <<:. This is backwards compatible with the 1.1 spec of yaml, it’s simply an explicit way of specifying the type (for instance, you can use a !!str tag to enforce a particular value to be a string.

Although this does affect the readability of the yaml to humans, it still works and processes fine with various yaml processors.