Strings

Strings are unstructured text fragments of any length. They’re a common and useful data type.

Strings can interpolate other values, and can use escape sequences to represent characters that are inconvenient or impossible to write literally. You can access substrings of a string by numerical index.

There are four ways to write literal strings in the Puppet language:
  • Bare words

  • Single-quoted strings

  • Double-quoted strings

  • Heredocs

Each of these have slightly different behavior around syntax, interpolation features, and escape sequences.

Bare words

Puppet treats certain bare words — that is, runs of alphanumeric characters without surrounding quotation marks — as single-word strings. Bare word strings are most commonly used with resource attributes that accept a limited number of one-word values.

To be treated as a string, a bare word must:
  • Begin with a lower case letter;

  • Contain only letters, digits, hyphens (-), and underscores (_); and

  • Not be a reserved word.

For example, in the following code, running is a bare word string:
service { "ntp":
  ensure => running, # bare word string
}
Unquoted words that begin with upper case letters are interpreted as data types or resource references, not strings.

Bare word strings can’t interpolate values and can’t use escape sequences.

Single-quoted strings

Multi-word strings can be surrounded by single quotation marks, 'like this'.

For example:
if $autoupdate {
  notice('autoupdate parameter has been deprecated and replaced with package_ensure.  Set this to latest for the same behavior as autoupdate => true.')
}

Line breaks within the string are interpreted as literal line breaks.

Single-quoted strings can’t interpolate values.

Escape sequences

The following escape sequences are available in single-quoted strings:
Sequence Result
\\ Single backslash
\' Literal single quotation mark
Within single quotation marks, if a backslash is followed by any character other than another backslash or a single quotation mark, Puppet treats it as a literal backslash.

To include a literal double backslash use a quadruple backslash.

To include a backslash at the very end of a single-quoted string, use a double backslash instead of a single backslash. For example: path => 'C:\Program Files(x86)\\'

Tip: A good habit is to always use two backslashes where you want the result to be one backslash. For example, path => 'C:\\Program Files(x86)\\'

Double-quoted strings

Strings can be surrounded by double quotation marks, "like this".

Line breaks within the string are interpreted as literal line breaks. You can also insert line breaks with \n (Unix-style) or \r\n (Windows-style).

Double-quoted strings can interpolate values. See Interpolation information below.

Escape sequences

The following escape sequences are available in double-quoted strings:
Sequence Result
\\ Single backslash
\n New line
\r Carriage return
\t Tab
\s Space
\$ Literal dollar sign (to prevent interpolation)
\uXXXX Unicode character number XXXX (a four-digit hexadecimal number)
\u{XXXXXX} Unicode character XXXXXX (a hexadecimal number between two and six digits)
\" Literal double quotation mark
\' Literal single quotation mark

Within double quotation marks, if a backslash is followed by any character other than those listed above (that is, a character that is not a recognized escape sequence), Puppet logs a warning: Warning: Unrecognized escape sequence, and treats it as a literal backslash.

Tip: A good habit is to always use two backslashes where you want the result to be one backslash.

Heredocs

Heredocs let you quote strings with more control over escaping, interpolation, and formatting. They’re especially good for long strings with complicated content.

Example

$gitconfig = @("GITCONFIG"/L)
    [user]
        name = ${displayname}
        email = ${email}
    [color]
        ui = true
    [alias]
        lg = "log --pretty=format:'%C(yellow)%h%C(reset) %s \
    %C(cyan)%cr%C(reset) %C(blue)%an%C(reset) %C(green)%d%C(reset)' --graph"
        wdiff = diff --word-diff=color --ignore-space-at-eol \
    --word-diff-regex='[[:alnum:]]+|[^[:space:][:alnum:]]+'
    [merge]
        defaultToUpstream = true
    [push]
        default = upstream
    | GITCONFIG

file { "${homedir}/.gitconfig":
  ensure  => file,
  content => $gitconfig,
}

Syntax

To write a heredoc, you place a heredoc tag in a line of code. This tag acts as a literal string value, but the content of that string is read from the lines that follow it. The string ends when an end marker is reached.

The general form of a heredoc string is:
heredoc tag
@("ENDTEXT"/<X>)

You can use a heredoc tag in Puppet code, anywhere a string value is accepted. In the above example, the heredoc tag @("GITCONFIG"/L) completes the line of Puppet code: $gitconfig = .

A heredoc tag starts with @( and ends with ).

Between those characters, the heredoc tag contains end text (see below) — text that is used to mark the end of the string. You can optionally surround this end text with double quotation marks to enable interpolation (see below). In the above example, the end text is GITCONFIG.

It also optionally contains escape switches (see below), which start with a slash /. In the above example, the heredoc tag has the escape switch /L.

the string
This is the
text that makes
up my string.

The content of the string starts on the next line, and can run over multiple lines. If you specified escape switches in the heredoc tag, the string can contain the enabled escape sequences.

In the above example, the string starts with [user] and ends with default = upstream. It uses the escape sequence \ to add cosmetic line breaks, because the heredoc tag contained the /L escape switch.

end marker
 | - ENDTEXT
On a line of its own, the end marker consists of:
  • Optional indentation and a pipe character (|) to indicate how much indentation is stripped from the lines of the string (see below).

  • An optional hyphen character (-), with any amount of space around it, to trim the final line break from the string (see below).

  • The end text, repeating the same end text used in the heredoc tag, always without quotation marks.

In the above example, the end marker is | GITCONFIG.

If a line of code includes more than one heredoc tag, Puppet reads all of those heredocs in order: the first one begins on the following line and continue until its end marker, the second one begins on the line immediately after the first end marker, and so on. Puppet won’t start evaluating additional lines of Puppet code until it reaches the end marker for the final heredoc tag from the original line.

End text

The heredoc tag contains piece of text called the end text. When Puppet reaches a line that contains only that end text (plus optional formatting control), the string ends.

Both occurrences of the end text must match exactly, with the same capitalization and internal spacing.

End text can be any run of text that doesn’t include line breaks, colons, slashes, or parentheses. It can include spaces, and can be mixed case. The following are all valid end text:
  • EOT

  • ...end...end...

  • Verse 8 of The Raven

Tip: To help with code readability, make your end text stand out from the content of the heredoc string, for example, by making it all uppercase.

Enabling interpolation

By default, heredocs do not allow you to interpolate values into the string content. You can enable interpolation by double-quoting the end text in the opening heredoc tag. That is:
  • An opening tag like @(EOT) won’t allow interpolation.

  • An opening tag like @("EOT") allows interpolation.

Note: If you enable interpolation, but the string has a dollar character ($) that you want to be literal, not interpolated, you must enable the literal dollar sign escape switch (/$) in the heredoc tag: @("EOT"/$). Then use the escape sequence \$ to specify the literal dollar sign in the string. See the information on enabling escape sequences, below, for more details.

Enabling escape sequences

By default, heredocs have no escape sequences and every character is literal (except interpolated expressions, if enabled). To enable escape sequences, add switches to the heredoc tag.

To enable individual escape sequences, add a slash (/) and one or more switches. For example, to enable an escape sequence for dollar signs (\$) and new lines (\n), add /$n to the heredoc tag :
@("EOT"/$n)
To enable all escape sequences, add a slash and no switches:
@("EOT"/)
Use the following switches to enable escape sequences:
Switch to put in the heredoc tag Escape sequence to use in the heredoc string Result in the string value
(automatic) \\ Single backslash. This switch is enabled when any other escape sequence is enabled.
n \n New line
r \r Carriage return
t \t Tab
s \s Space
$ \$ Literal dollar sign (to prevent interpolation)
u \uXXXX or \u{XXXXXX} Unicode character number XXXX (a four-digit hexadecimal number) or XXXXXX (a two- to six-digit hexadecimal number)
L \<New line or carriage return> Nothing. This lets you put line breaks in the heredoc source code that does not appear in the string value.
Note: A backslash that isn't part of an escape sequence is treated as a literal backslash. Unlike in double-quoted strings, this does not log a warning.
Tip: If a heredoc has escapes enabled, and includes several literal backslashes in a row, make sure each literal backslash is represented by the \\ escape sequence. So, for example, If you want the result to include a double backslash, use four backslashes.

Enabling syntax checking

To enable syntax checking of heredoc text, add the name of the syntax to the heredoc tag. For example:
@(END:pp)
@(END:epp)
@(END:json)

If Puppet has a syntax checker for the given syntax, it validates the heredoc text, but only if the heredoc is static text and does not contain any interpolations. If Puppet has no checker available for the given syntax, it silently ignores the syntax tag.

Syntax checking in heredocs is useful for validating syntax earlier, avoiding later failure.

By default, heredocs are treated as text unless otherwise specified in the heredoc tag.

Stripping indentation

To make your code easier to read, you can indent the content of a heredoc to separate it from the surrounding code. To strip this indentation from the resulting string value, put the same amount of indentation in front of the end marker and use a pipe character (|) to indicate the position of the first “real” character on each line.
$mytext = @(EOT)
    This block of text is
    visibly separated from
    everything around it.
    | EOT
If a line has less indentation than you’ve indicated with the pipe, Puppet strips any spaces it can without deleting non-space characters.

If a line has more indentation than you’ve indicated with the pipe, the excess spaces are included in the final string value.

Important: Indentation can include tab characters, but Puppet won’t convert tabs to spaces, so make sure you use the exact same sequence of space and tab characters on each line.

Suppressing literal line breaks

If you enable the L escape switch, you can end a line with a backslash (\) to exclude the following line break from the string value. This lets you break up long lines in your source code without adding unwanted literal line breaks to the resulting string value.

For example, Puppet would read this as a single line:
lg = "log --pretty=format:'%C(yellow)%h%C(reset) %s \
%C(cyan)%cr%C(reset) %C(blue)%an%C(reset) %C(green)%d%C(reset)' --graph"

Suppressing the final line break

By default, heredocs end with a trailing line break, but you can exclude this line break from the final string. To suppress it, add a hyphen (-) to the end marker, before the end text, but after the indentation pipe if you used one. This works even if you don’t have the L escape switch enabled.

For example, Puppet would read this as a string with no line break at the end:
$mytext = @("EOT")
    This is too inconvenient for ${double} or ${single} quotes, but must be one line.
    |-EOT

Interpolation

Interpolation allows strings to contain expressions, which can be replaced with their values. You can interpolate any expression that resolves to a value, except for statement-style function calls. You can interpolate expressions in double-quoted strings, and in heredocs with interpolation enabled.

To interpolate an expression, start with a dollar sign and wrap the expression in curly braces, as in: "String content ${<EXPRESSION>} more content".

The dollar sign doesn’t have to have a space in front of it. It can be placed directly after any other character, or at the beginning of the string.

An interpolated expression can include quote marks that would end the string if they occurred outside the interpolation token. For example: "<VirtualHost *:${hiera("http_port")}>".

Preventing interpolation

If you want a string to include a literal sequence that looks like an interpolation token, but you don't want Puppet to try to evaluate it, use a quoting syntax that disables interpolation (single quotes or a non-interpolating heredoc), or escape the dollar sign with \$.

Short forms for variable interpolation

The most common thing to interpolate into a string is the value of a variable. To make this easier, Puppet has some shorter forms of the interpolation syntax:
$myvariable
A variable reference (without curly braces) can be replaced with that variable’s value. This also works with qualified variable names like $myclass::myvariable.
Because this syntax doesn’t have an explicit stopping point (like a closing curly brace), Puppet assumes the variable name is everything between the dollar sign and the first character that couldn’t legally be part of a variable name. (Or the end of the string, if that comes first.)
This means you can’t use this style of interpolation when a value must run up against some other word-like text. And even in some cases where you can use this style, the following style can be clearer.
${myvariable}
A dollar sign followed by a variable name in curly braces can be replaced with that variable’s value. This also works with qualified variable names like ${myclass::myvariable}.
With this syntax, you can follow a variable name with any combination of chained function calls or hash access / array access / substring access expressions. For example:
"Using interface ${::interfaces.split(',')[3]} for broadcast"
However, this doesn’t work if the variable’s name overlaps with a language keyword. For example, if you had a variable called $inherits, you would have to use normal-style interpolation:
"Inheriting ${$inherits.upcase}."

Conversion of interpolated values

Puppet converts the value of any interpolated expression to a string using these rules:
Data type Conversion
String The contents of the string, with any quoting syntax removed.
Undef An empty string.
Boolean The string 'true' or 'false'.
Number The number in decimal notation (base 10). For floats, the value can vary on different platforms. Use the sprintf function for more precise formatting.
Array A pair of square brackets ([ and ]) containing the array’s elements, separated by a comma and a space (, ), with no trailing comma. Each element is converted to a string using these rules.
Hash A pair of curly braces ({ and }) containing a <KEY> => <VALUE> string for each key-value pair, separated by a comma and a space (, ), with no trailing comma. Each key and value is converted to a string using these rules.
Regular expression A stringified regular expression.
Resource reference or data type The value as a string.

Line breaks

Quoted strings can continue over multiple lines, and line breaks are preserved as a literal part of the string. Heredocs let you suppress these line breaks if you use the L escape switch.

Puppet does not attempt to convert line breaks, so whatever type of line break is used in the file (LF for *nix or CRLF for Windows) is preserved. Use escape sequences to insert specific types of line breaks into strings:
  • To insert a CRLF in a manifest file that uses *nix line endings, use the \r\n escape sequences in a double-quoted string, or a heredoc with those escapes enabled.

  • To insert an LF in a manifest that uses Windows line endings, use the \n escape sequence in a double-quoted string, or a heredoc with that escape enabled.

Encoding

Puppet treats strings as sequences of bytes. It does not recognize encodings or translate between them, and non-printing characters are preserved.

However, all strings must be valid UTF-8. Future versions of Puppet might impose restrictions on string encoding, and using only UTF-8 protects you in this event. Also, PuppetDB removes invalid UTF-8 characters when storing catalogs.

Accessing substrings

Access substrings of a string by specifying a numerical index inside square brackets. The index consists of one integer, optionally followed by a comma and a second integer, for example $string[3] or $string[3,10].

The first number of the index is the start position. Positive numbers count from the start of the string, starting at 0. Negative numbers count back from the end of the string, starting at -1.

The second number of the index is the stop position. Positive numbers are lengths, counting forward from the start position. Negative numbers are absolute positions, counting back from the end of the string (starting at -1). If the second number is omitted, it defaults to 1 (resolving to a single character).

Examples:
$mystring = 'abcdef'
notice( $mystring[0] )    # resolves to 'a'
notice( $mystring[0,2] )  # resolves to 'ab'
notice( $mystring[1,2] )  # resolves to 'bc'
notice( $mystring[1,-2] ) # resolves to 'bcde'
notice( $mystring[-3,2] ) # resolves to 'de'
Text outside the actual range of the string is treated as an infinite amount of empty string:
$mystring = 'abcdef'
notice( $mystring[10] )    # resolves to ''
notice( $mystring[3,10] )  # resolves to 'def'
notice( $mystring[-10,2] ) # resolves to ''
notice( $mystring[-10,6] ) # resolves to 'ab'

The String data type

The data type of strings is String. By default, String matches strings of any length. You can use parameters to restrict which values String matches.

Parameters

The full signature for String is:
String[<MIN LENGTH>, <MAX LENGTH>]
These parameters are optional. They must be listed in order; if you need to specify a later parameter, you must also specify values for any prior ones.
Position Parameter Data type Default value Description
1 Minimum length Integer 0 The minimum number of (Unicode) characters in the string. This parameter accepts the special value default, which uses its default value.
2 Maximum length Integer infinite The maximum number of (Unicode) characters in the string. This parameter accepts the special value default, which uses its default value.
Examples:
String
Matches a string of any length.
String[6]
Matches a string with at least six characters.
String[6,8]
Matches a string with at least six and at most eight characters.