YAML Cheatsheet

Multiline Strings

Use this YAML reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

The two block styles and three chomping modes

A block scalar starts with an indicator on the key's line, then an indented block. The indicator is one style character plus an optional chomping character.

StyleNewlines inside
| literalkept exactly as written
> foldedsingle newlines become spaces, blank lines become newlines
ChompingTrailing newlines
(none) clipexactly one \n at the end
- stripno trailing \n
+ keepevery trailing blank line kept

That is six combinations: |, |-, |+, >, >-, >+.

The complete matrix

One source block, run through all six. Everything below was parsed with PyYAML 6.0, not recalled. The source, with a deliberate blank line inside and a trailing blank line:

s: |
  line one
  line two

  line four

Results, written as unambiguous string literals so trailing newlines are visible:

IndicatorExact resulting string
|"line one\nline two\n\nline four\n"
|-"line one\nline two\n\nline four"
|+"line one\nline two\n\nline four\n\n"
>"line one line two\nline four\n"
>-"line one line two\nline four"
>+"line one line two\nline four\n\n"

Read as text, | gives four lines and > gives two:

|   ->  line one
        line two
        <blank>
        line four
        <one trailing newline>

>   ->  line one line two
        line four
        <one trailing newline>

The blank line is what survives folding. > joins line one and line two with a space because they are consecutive non-blank lines, then the blank line becomes the single \n separating them from line four.

Folding in detail

SourceFolded result
a b c"a b c\n"
a · blank · b"a\nb\n"
a · blank · blank · b"a\n\nb\n"
a b c d deeper back"a b c d\n deeper\nback\n"

A more-indented line is not folded. That is how you keep a code block inside a folded scalar. Note the leading spaces survive.

description: >
  Normal prose folds onto
  one long line.

    this indented line
    stays on its own lines

  And prose resumes.

Two things bite here. Trailing whitespace on a line inside a > block is preserved and then the fold space is added, so a followed by b folds to "a b" with four spaces. Strip trailing whitespace before committing. And a line that folds is one long line to whatever consumes it, so a > block is wrong for anything line-oriented (a shell script, a certificate, a CSV).

Which one to use

Use caseIndicator
shell script, Dockerfile RUN, SQL|
PEM certificate or key|
commit-message style prose>
a long single-line value wrapped for readability>-
a value that must not end in a newline|- or >-
a value whose exact trailing blank lines matter|+

Default to | for anything you would paste into a terminal, and >- for a long sentence you are only wrapping to fit the column.

command: |
  set -euo pipefail
  echo "starting"
  exec ./server --port 8080

summary: >-
  A single long sentence that happens to be wrapped in
  the source file and arrives as one line with no
  trailing newline.

The indentation indicator

Indentation is normally inferred from the first non-empty line of the block. Two cases break that, and both are fixed with an explicit digit after the style character.

Case 1, the content starts with spaces you want to keep.

s: |2
    keeps two spaces

Content is indented four, the indicator says the block indent is two, so the result is " keeps two spaces\n". Without the 2 the first line sets the indent and you get "keeps two spaces\n".

Case 2, the first line is more indented than the rest. This is a hard parse error, not a silent reinterpretation:

s: |
   three spaces
  two spaces

fails with a ParserError. Add |2 and it parses to " three spaces\ntwo spaces\n".

The digit is 1-9 and counts from the parent node's indentation, not from column zero.

Details worth knowing

- A comment may follow the indicator on the same line: s: | # note is legal and the comment is discarded. - An empty block (s: | with nothing under it) is the empty string "", not null. - The block ends at the first line indented less than the block indent, so a following sibling key just works. No terminator is needed. - |+ at end of file keeps only the newlines actually present, so s: |+ with one line gives "a\n", the same as |. - Tabs inside the block content are fine. Tabs in the block indentation are not, same as everywhere else in YAML. - A block scalar cannot appear in flow style. {msg: | is a scan error, so a multi-line value forces block style or the double-quoted "a\nb" form.