Skip to content
datahacks.dev
YAML

YAML Multiline Strings With Pipe and Greater Than Signs

The pipe keeps line breaks, the greater than sign folds them, and chomping indicators control the final newline. Six variants and the exact strings.

5 min read
Summarize in AI
Flat illustration of a tree of nested objects beside the document it came from, with the YAML logo.

Real configuration contains text that does not fit on a line: a shell script in a CI step, a SQL query, a PEM certificate, a long description. YAML has two block styles for this, written with a pipe or a greater than sign after the key, and a small modifier that controls what happens to the final line break. Learning the six combinations once saves a lot of trial and error. All the strings below are the exact output of a parser.

The two styles

**Literal style, |.** Every line break in the block is kept. What you write is what you get, minus the indentation.

**Folded style, >.** Single line breaks become spaces, so the block reads as one long line. A blank line becomes a line break, which is how you separate paragraphs.

Both take the content from the lines that are indented more than the key, starting with the line after the indicator. The first non-empty line sets the indentation of the block, and the block ends at the first line that is indented less.

The test text, with the key k:

YAML
k: |
  line one
  line two

  line four

next: 1

The six variants

The text is the same in each case. Only the indicator changes. The Python strings that came out:

Text
|   '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 it in two directions.

Across styles. The pipe keeps line one, line two, the blank line and line four as written, with \n between each. The greater-than style joined the first two lines with a space (line one line two) and turned the blank line into one \n, then continued with line four. That is the folding rule: a single newline between two non-empty lines becomes a space, and a blank line becomes a newline.

Across the chomping modifier. After the style indicator you may put a chomping indicator, which says what to do with the line break at the end and any blank lines after it:

  • No modifier (clip): keep exactly one final newline. This is the default and what most scripts want.

  • **- (strip):** remove the final newline. The string ends with line four and nothing else.

  • **+ (keep):** keep the final newline and every blank line after it. Here two \n at the end, because one blank line followed the text before the next key.

The difference between clip and strip matters in practice. A shell command from run: | ends in a newline, which is normal. A value you will compare with another string, such as an expected output or a name, should use |- or >- to avoid a trailing newline that breaks the comparison.

Plain and quoted multiline strings

You can also continue a plain or quoted scalar across lines without any indicator:

YAML
k: first
  second
  third
Text
'first second third'

Continuation lines are folded with spaces, the same rule as the greater-than style. This works for long descriptions, and it is fragile: the continuation lines must be indented more than the key, and a line that contains : or # breaks it. In double-quoted strings, a backslash at the end of a line joins without a space. Block style with an explicit indicator is clearer for anything over one line.

Indentation is content

Inside a block scalar the leading spaces matter. The first non-empty line decides the base indentation, and extra indentation on later lines is kept:

YAML
script: |
  if true; then
    echo "nested"
  fi

The string has two spaces before echo, preserving the shell's formatting. In folded style, lines that are more indented than the base are not folded: they keep their line breaks, which is useful for code samples inside prose and surprising otherwise.

If the first line of the block is itself indented more than the lines that follow, the parser cannot know which indentation you meant, and you must give it an explicit indentation indicator, a digit after the style (|2). This is rare. The usual mistake is a tab or inconsistent spaces in the block, which gives a parse error (finding tab characters hiding in a YAML file).

Trailing spaces at the end of lines inside a literal block are preserved, invisibly. A script with a trailing space after a backslash line continuation breaks in the shell, and the YAML looks fine. Turn on trailing-whitespace trimming in your editor, and lint (linting YAML with yamllint).

Choosing

ContentUseWhy
Shell script, SQL, code|Line breaks are meaningful
Certificate or key|The line structure is part of the format
Long description or message> or >-One logical line, wrapped for readers
Text compared with something|- or >-No trailing newline
Paragraphs> with blank linesBlank line becomes a paragraph break
One short linePlain or quotedNo block needed

And two cautions. A literal block is not a template: it does not expand variables, so $HOME inside a CI run: | step is passed to the shell as is, and the shell expands it. And a block scalar cannot have a comment on its content lines, since a # there is content. Put comments above the key.

The cluster hub is YAML syntax you need to stop guessing at. For the rest of the scalar rules, see YAML strings, quoting and when you need quotes and the indentation basics in YAML indentation rules and why tabs break everything. The block scalars are specified in chapter 8 of the YAML 1.2.2 specification, and a visual reference at yaml-multiline.info. Check how a block loads in the YAML to JSON tool.

When block scalars are the wrong tool

The text is large or binary. A 40 KB certificate bundle or a base64 blob in the middle of a config file hides the structure. Put it in its own file and refer to the path.

The text needs interpolation. If values must be filled in, use a templating step after parsing, with the escaping rules of the target language (environment variable substitution in YAML config).

A tool rewrites the file. Some libraries save block scalars as quoted strings with escapes, destroying the readable layout. Use a round-trip library, or accept the churn (writing YAML from Python without ugly output).

The consumer needs exact bytes. Windows line endings, tabs and trailing spaces do not survive an editor reliably. Encode the exact content in a separate file.

Also inTooling
Share

Keep reading

Get new articles by email

We send one email when a new article is published. No spam.

Unsubscribe in one click. No spam, ever.