- OpenTofu 语言
- 表达式
- 字符串和模板
字符串和模板
字符串字面量是 OpenTofu 中最复杂的一种字面量表达式,也是最常用的。
OpenTofu 支持带引号的语法和 "heredoc" 语法来表示字符串。这两种语法都支持模板序列,用于插入值和操作文本。
带引号的字符串
带引号的字符串是由一对双引号 ("
) 括起来的字符序列。
"hello"
转义序列
在带引号的字符串中,反斜杠字符充当转义序列,以下字符选择转义行为
序列 | 替换 |
---|---|
\n | 换行符 |
\r | 回车符 |
\t | 制表符 |
\" | 字面引号(不终止字符串) |
\\ | 字面反斜杠 |
\uNNNN | 基本多语言平面上的 Unicode 字符 (NNNN 是四个十六进制数字) |
\UNNNNNNNN | 补充平面上的 Unicode 字符 (NNNNNNNN 是八个十六进制数字) |
还有两个不使用反斜杠的特殊转义序列
序列 | 替换 |
---|---|
$${ | 字面量 ${ ,不会开始插值序列。 |
%%{ | 字面量 %{ ,不会开始模板指令序列。 |
Heredoc 字符串
OpenTofu 还支持受 Unix shell 语言启发的 "heredoc" 风格的字符串字面量,它允许更清晰地表达多行字符串。
<<EOT
hello
world
EOT
Heredoc 字符串由以下部分组成:
- 一个开头序列,包含:
- 一个 heredoc 标记 (
<<
或<<-
- 两个小于号,可选地带一个连字符用于缩进的 heredoc) - 一个您选择的定界符单词
- 一个换行符
- 一个 heredoc 标记 (
- 字符串的内容,可以跨越任意数量的行
- 您选择的定界符单词,单独占据一行(缩进的 heredoc 允许缩进)
<<
标记后跟任何标识符,出现在一行的末尾,将引入该序列。OpenTofu 然后处理接下来的行,直到找到一个完全由引入器中给定的标识符组成的行。
在上面的示例中,EOT
是选择的标识符。任何标识符都是允许的,但是按照惯例,该标识符使用全大写字母,并且以 EO
开头,表示 "end of"。在本例中,EOT
代表 "end of text"。
生成 JSON 或 YAML
不要使用 "heredoc" 字符串来生成 JSON 或 YAML。相反,请使用 jsonencode
函数 或 yamlencode
函数,以便 OpenTofu 可以负责保证有效的 JSON 或 YAML 语法。
example = jsonencode({
a = 1
b = "hello"
})
缩进的 Heredocs
标准的 heredoc 形式(如上所示)将所有空格字符都视为字面空格。如果您不希望每行都以空格开头,那么每行都必须与左边缘对齐,这对缩进块中的表达式来说可能很麻烦。
block {
value = <<EOT
hello
world
EOT
}
为了改进这一点,OpenTofu 还接受一种名为缩进的 heredoc 字符串变体,它由 <<-
序列引入。
block {
value = <<-EOT
hello
world
EOT
}
在这种情况下,OpenTofu 会分析序列中的行,找到开头空格最少的行,然后从所有行的开头删除这么多空格,从而产生以下结果。
hello
world
转义序列
反斜杠序列在 heredoc 字符串表达式中不会被解释为转义符。相反,反斜杠字符会被直接解释。
Heredocs 支持两个不使用反斜杠的特殊转义序列
序列 | 替换 |
---|---|
$${ | 字面量 ${ ,不会开始插值序列。 |
%%{ | 字面量 %{ ,不会开始模板指令序列。 |
字符串模板
在带引号的和 heredoc 字符串表达式中,${
和 %{
序列会开始模板序列。模板允许您将表达式直接嵌入到字符串字面量中,以动态地从其他值构建字符串。
插值
${ ... }
序列是插值,它会计算标记之间的表达式,如果需要则将结果转换为字符串,然后将其插入到最终的字符串中。
"Hello, ${var.name}!"
在上面的示例中,会访问名为 var.name
的对象,并将它的值插入到字符串中,从而产生类似 "Hello, Juan!" 的结果。
指令
%{ ... }
序列是指令,它允许根据条件生成结果,并迭代集合,类似于条件表达式和 for
表达式。
支持以下指令:
-
%{if <BOOL>}
/%{else}
/%{endif}
指令根据布尔表达式的值在两个模板之间进行选择。代码块 "Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!"
可以省略
else
部分,在这种情况下,如果条件表达式返回false
,则结果为空字符串。 -
%{for <NAME> in <COLLECTION>}
/%{endfor}
指令会迭代给定集合或结构化值中的元素,并针对每个元素评估给定的模板一次,并将结果拼接在一起。代码块 <<EOT
%{ for ip in aws_instance.example[*].private_ip }
server ${ip}
%{ endfor }
EOTfor
关键字后面的名称用作临时变量名称,然后可以在嵌套的模板中引用。
空格去除
为了允许模板指令为了可读性而格式化,而不会在结果中添加不需要的空格和换行符,所有模板序列都可以包含可选的 *剥离标记* (~
),紧接在开始字符之后或结束之前。当存在剥离标记时,模板序列将消耗所有字面空白(空格和换行符),这些空白要么在序列之前(如果标记出现在开头),要么在序列之后(如果标记出现在结尾)。
<<EOT
%{ for ip in aws_instance.example[*].private_ip ~}
server ${ip}
%{ endfor ~}
EOT
在上面的示例中,每个指令后的换行符不包含在输出中,但server ${ip}
序列后的换行符保留,导致每个元素只生成一行。
server 10.1.16.154
server 10.1.16.1
server 10.1.16.34
在使用模板指令时,我们建议始终使用“heredoc”字符串文字形式,然后将模板格式化成多行以提高可读性。引用的字符串文字通常只应包含插值序列。