223 lines
7.1 KiB
Markdown
223 lines
7.1 KiB
Markdown
---
|
||
layout: "language"
|
||
page_title: "Strings and Templates - Configuration Language"
|
||
---
|
||
|
||
# Strings and Templates
|
||
|
||
String literals are the most complex kind of literal expression in
|
||
Terraform, and also the most commonly used.
|
||
|
||
Terraform supports both a quoted syntax and a "heredoc" syntax for strings.
|
||
Both of these syntaxes support template sequences for interpolating values and
|
||
manipulating text.
|
||
|
||
## Quoted Strings
|
||
|
||
A quoted string is a series of characters delimited by straight double-quote
|
||
characters (`"`).
|
||
|
||
```
|
||
"hello"
|
||
```
|
||
|
||
### Escape Sequences
|
||
|
||
In quoted strings, the backslash character serves as an escape
|
||
sequence, with the following characters selecting the escape behavior:
|
||
|
||
| Sequence | Replacement |
|
||
| ------------ | ----------------------------------------------------------------------------- |
|
||
| `\n` | Newline |
|
||
| `\r` | Carriage Return |
|
||
| `\t` | Tab |
|
||
| `\"` | Literal quote (without terminating the string) |
|
||
| `\\` | Literal backslash |
|
||
| `\uNNNN` | Unicode character from the basic multilingual plane (NNNN is four hex digits) |
|
||
| `\UNNNNNNNN` | Unicode character from supplementary planes (NNNNNNNN is eight hex digits) |
|
||
|
||
There are also two special escape sequences that do not use backslashes:
|
||
|
||
| Sequence | Replacement |
|
||
| --- | ---- |
|
||
| `$${` | Literal `${`, without beginning an interpolation sequence. |
|
||
| `%%{` | Literal `%{`, without beginning a template directive sequence. |
|
||
|
||
## Heredoc Strings
|
||
|
||
Terraform also supports a "heredoc" style of string literal inspired by Unix
|
||
shell languages, which allows multi-line strings to be expressed more clearly.
|
||
|
||
```hcl
|
||
<<EOT
|
||
hello
|
||
world
|
||
EOT
|
||
```
|
||
|
||
A heredoc string consists of:
|
||
|
||
- An opening sequence consisting of:
|
||
- A heredoc marker (`<<` or `<<-` — two less-than signs, with an optional hyphen for indented heredocs)
|
||
- A delimiter word of your own choosing
|
||
- A line break
|
||
- The contents of the string, which can span any number of lines
|
||
- The delimiter word you chose, alone on its own line (with indentation allowed for indented heredocs)
|
||
|
||
The `<<` marker followed by any identifier at the end of a line introduces the
|
||
sequence. Terraform then processes the following lines until it finds one that
|
||
consists entirely of the identifier given in the introducer.
|
||
|
||
In the above example, `EOT` is the identifier selected. Any identifier is
|
||
allowed, but conventionally this identifier is in all-uppercase and begins with
|
||
`EO`, meaning "end of". `EOT` in this case stands for "end of text".
|
||
|
||
### Generating JSON or YAML
|
||
|
||
Don't use "heredoc" strings to generate JSON or YAML. Instead, use
|
||
[the `jsonencode` function](../functions/jsonencode.html) or
|
||
[the `yamlencode` function](../functions/yamlencode.html) so that Terraform
|
||
can be responsible for guaranteeing valid JSON or YAML syntax.
|
||
|
||
```hcl
|
||
example = jsonencode({
|
||
a = 1
|
||
b = "hello"
|
||
})
|
||
```
|
||
|
||
### Indented Heredocs
|
||
|
||
The standard heredoc form (shown above) treats all space characters as literal
|
||
spaces. If you don't want each line to begin with spaces, then each line must be
|
||
flush with the left margin, which can be awkward for expressions in an
|
||
indented block:
|
||
|
||
```hcl
|
||
block {
|
||
value = <<EOT
|
||
hello
|
||
world
|
||
EOT
|
||
}
|
||
```
|
||
|
||
To improve on this, Terraform also accepts an _indented_ heredoc string variant
|
||
that is introduced by the `<<-` sequence:
|
||
|
||
```hcl
|
||
block {
|
||
value = <<-EOT
|
||
hello
|
||
world
|
||
EOT
|
||
}
|
||
```
|
||
|
||
In this case, Terraform analyses the lines in the sequence to find the one
|
||
with the smallest number of leading spaces, and then trims that many spaces
|
||
from the beginning of all of the lines, leading to the following result:
|
||
|
||
```
|
||
hello
|
||
world
|
||
```
|
||
|
||
### Escape Sequences
|
||
|
||
Backslash sequences are not interpreted as escapes in a heredoc string
|
||
expression. Instead, the backslash character is interpreted literally.
|
||
|
||
Heredocs support two special escape sequences that do not use backslashes:
|
||
|
||
| Sequence | Replacement |
|
||
| --- | ---- |
|
||
| `$${` | Literal `${`, without beginning an interpolation sequence. |
|
||
| `%%{` | Literal `%{`, without beginning a template directive sequence. |
|
||
|
||
|
||
## String Templates
|
||
|
||
Within quoted and heredoc string expressions, the sequences `${` and `%{` begin
|
||
_template sequences_. Templates let you directly embed expressions into a string
|
||
literal, to dynamically construct strings from other values.
|
||
|
||
### Interpolation
|
||
|
||
A `${ ... }` sequence is an _interpolation,_ which evaluates the expression
|
||
given between the markers, converts the result to a string if necessary, and
|
||
then inserts it into the final string:
|
||
|
||
```hcl
|
||
"Hello, ${var.name}!"
|
||
```
|
||
|
||
In the above example, the named object `var.name` is accessed and its value
|
||
inserted into the string, producing a result like "Hello, Juan!".
|
||
|
||
### Directives
|
||
|
||
A `%{ ... }` sequence is a _directive_, which allows for conditional
|
||
results and iteration over collections, similar to conditional
|
||
and `for` expressions.
|
||
|
||
The following directives are supported:
|
||
|
||
* The `%{if <BOOL>}`/`%{else}`/`%{endif}` directive chooses between two templates based
|
||
on the value of a bool expression:
|
||
|
||
```hcl
|
||
"Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!"
|
||
```
|
||
|
||
The `else` portion may be omitted, in which case the result is an empty
|
||
string if the condition expression returns `false`.
|
||
|
||
* The `%{for <NAME> in <COLLECTION>}` / `%{endfor}` directive iterates over the
|
||
elements of a given collection or structural value and evaluates a given
|
||
template once for each element, concatenating the results together:
|
||
|
||
```hcl
|
||
<<EOT
|
||
%{ for ip in aws_instance.example.*.private_ip }
|
||
server ${ip}
|
||
%{ endfor }
|
||
EOT
|
||
```
|
||
|
||
The name given immediately after the `for` keyword is used as a temporary
|
||
variable name which can then be referenced from the nested template.
|
||
|
||
### Whitespace Stripping
|
||
|
||
To allow template directives to be formatted for readability without adding
|
||
unwanted spaces and newlines to the result, all template sequences can include
|
||
optional _strip markers_ (`~`), immediately after the opening characters or
|
||
immediately before the end. When a strip marker is present, the template
|
||
sequence consumes all of the literal whitespace (spaces and newlines) either
|
||
before the sequence (if the marker appears at the beginning) or after (if the
|
||
marker appears at the end):
|
||
|
||
```hcl
|
||
<<EOT
|
||
%{ for ip in aws_instance.example.*.private_ip ~}
|
||
server ${ip}
|
||
%{ endfor ~}
|
||
EOT
|
||
```
|
||
|
||
In the above example, the newline after each of the directives is not included
|
||
in the output, but the newline after the `server ${ip}` sequence is retained,
|
||
causing only one line to be generated for each element:
|
||
|
||
```
|
||
server 10.1.16.154
|
||
server 10.1.16.1
|
||
server 10.1.16.34
|
||
```
|
||
|
||
When using template directives, we recommend always using the "heredoc" string
|
||
literal form and then formatting the template over multiple lines for
|
||
readability. Quoted string literals should usually include only interpolation
|
||
sequences.
|