如何在 Terraform local-exec 命令行中转义特殊字符
How to escape special characters in Terraform local-exec command line
我有以下地形:
resource "null_resource" "cognito_user_pool_client_id" {
triggers = { always_run = "${timestamp()}" }
provisioner "local-exec" {
command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
depends_on = ["aws_cognito_user_pool_domain.main"]
}
我试图从 cognito 中的用户池中获取应用程序客户端 ID。无论如何,这条线因地形而失败:
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
This character is not used within the language.
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
Single quotes are not valid. Use double quotes (") to enclose strings.
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
This character is not used within the language.
这适用于 aws cli :
(venv) ➜ virginia git:(master) ✗ aws cognito-idp list-user-pool-clients --user-pool-id 123456 --region us-east-1 | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$'
dsewe24dwr2e
如何在 terraform 中实现此功能?
这里有几种不同的“语言”需要处理,每种语言都可能需要进行一些转义以包含其中的语言,但是由于您特别询问了 Terraform,我将重点关注第一层转义,以确保 shell 看到您希望它看到的字符串。
这部分 Terraform 语言语法的相关文档是 Strings and Templates,其中讨论了 Terraform 语言中的两种不同类型的字符串以及它们各自提供的转义类型。
您当前使用的是 quoted string,因此您需要同时处理引用字符串转义 和 模板转义。您想要的字符串仅与引号转义的字符串交互,因为它包含一些您希望由 shell 而不是 Terraform 处理的文字引号字符 "
,因此您可以将它们转义为 \"
就像文档建议的那样:
command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '\"ClientId\": \"[^\"]*' | grep -o '[^\"]*$' > ${path.module}/cognito_app_client.txt"
为了完整起见,我还要说 Unix shells 通常也支持 ${NAME}
语法作为 $NAME
的替代方法,在后者会产生歧义的情况下。 ${NAME}
与 Terraform 的模板语法冲突,因此如果您想在 shell 命令中包含像 that 这样的序列,那么您需要将其转义,如图所示在文档的第二个 table 中,改为写 $${NAME}
。
如果您阅读有关 heredoc strings 的下一节,您会发现它们的一个好处是它们没有用引号分隔,因此内容不会被解释为反斜杠转义序列,因此您可以按字面意思写引号和其他特殊字符:
command = <<-EOT
aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt
EOT
Terraform 确实 仍然在此处解释模板序列 ${ ... }
和 %{ ... }
,所以如果您有文字 ${NAME}
序列用于 shell 在这种情况下,您仍然需要将它们写成 $${NAME}
,但是您 不再 需要转义引号,因为这种类型的字符串由一个更长的、用户指定的标记 EOT
,允许将内部引号视为文字。
使用 heredoc 字符串的另一个优点是您可以将命令拆分为多行,这可能更易于阅读:
command = <<-EOT
aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} \
| grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt
EOT
请注意,Unix shells 通常需要使用 \
转义换行符以避免将其解释为两个单独的命令,因此我将其包含在上面的示例中,但从 Terraform 的角度来看,这只是模板扩展完成后要传递给 shell 的两行字符串。
我有以下地形:
resource "null_resource" "cognito_user_pool_client_id" {
triggers = { always_run = "${timestamp()}" }
provisioner "local-exec" {
command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
depends_on = ["aws_cognito_user_pool_domain.main"]
}
我试图从 cognito 中的用户池中获取应用程序客户端 ID。无论如何,这条线因地形而失败:
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
This character is not used within the language.
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
Single quotes are not valid. Use double quotes (") to enclose strings.
Error: Invalid character
on kibana_cognito.tf line 163, in resource "null_resource" "cognito_user_pool_client_id":
163: command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt"
This character is not used within the language.
这适用于 aws cli :
(venv) ➜ virginia git:(master) ✗ aws cognito-idp list-user-pool-clients --user-pool-id 123456 --region us-east-1 | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$'
dsewe24dwr2e
如何在 terraform 中实现此功能?
这里有几种不同的“语言”需要处理,每种语言都可能需要进行一些转义以包含其中的语言,但是由于您特别询问了 Terraform,我将重点关注第一层转义,以确保 shell 看到您希望它看到的字符串。
这部分 Terraform 语言语法的相关文档是 Strings and Templates,其中讨论了 Terraform 语言中的两种不同类型的字符串以及它们各自提供的转义类型。
您当前使用的是 quoted string,因此您需要同时处理引用字符串转义 和 模板转义。您想要的字符串仅与引号转义的字符串交互,因为它包含一些您希望由 shell 而不是 Terraform 处理的文字引号字符 "
,因此您可以将它们转义为 \"
就像文档建议的那样:
command = "aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '\"ClientId\": \"[^\"]*' | grep -o '[^\"]*$' > ${path.module}/cognito_app_client.txt"
为了完整起见,我还要说 Unix shells 通常也支持 ${NAME}
语法作为 $NAME
的替代方法,在后者会产生歧义的情况下。 ${NAME}
与 Terraform 的模板语法冲突,因此如果您想在 shell 命令中包含像 that 这样的序列,那么您需要将其转义,如图所示在文档的第二个 table 中,改为写 $${NAME}
。
如果您阅读有关 heredoc strings 的下一节,您会发现它们的一个好处是它们没有用引号分隔,因此内容不会被解释为反斜杠转义序列,因此您可以按字面意思写引号和其他特殊字符:
command = <<-EOT
aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} | grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt
EOT
Terraform 确实 仍然在此处解释模板序列 ${ ... }
和 %{ ... }
,所以如果您有文字 ${NAME}
序列用于 shell 在这种情况下,您仍然需要将它们写成 $${NAME}
,但是您 不再 需要转义引号,因为这种类型的字符串由一个更长的、用户指定的标记 EOT
,允许将内部引号视为文字。
使用 heredoc 字符串的另一个优点是您可以将命令拆分为多行,这可能更易于阅读:
command = <<-EOT
aws cognito-idp list-user-pool-clients --user-pool-id ${aws_cognito_user_pool.main.id} --region ${var.region} \
| grep -o '"ClientId": "[^"]*' | grep -o '[^"]*$' > ${path.module}/cognito_app_client.txt
EOT
请注意,Unix shells 通常需要使用 \
转义换行符以避免将其解释为两个单独的命令,因此我将其包含在上面的示例中,但从 Terraform 的角度来看,这只是模板扩展完成后要传递给 shell 的两行字符串。