Bash EOF block in EOF block possible?

Viewed 358

I'm trying to write in a file a block containing its own EOF block. Is it something doable in bash?

cat > terragrunt.hcl <<'EOF' 
# Automatically generated from script $(basename $0)

# Generate the AWS provider block
generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
# Terragrunt root config
provider "aws" {
  # Only these AWS Account IDs may be operated on by this template
  allowed_account_ids = ["${local.account_id}"]
  region = "${local.infra_region}"
  version = "${local.customer_vars.locals.aws_provider_version}"
}
EOF
}

# Automatically generated from script $(basename $0)
EOF

As expected it is failing with:

❯ ./example.sh 
./example.sh: line 17: syntax error near unexpected token `}'
./example.sh: line 17: `}'

What is the best solution to deal with it?

1 Answers

What you are calling an "EOF block" is actually called a "Here Document" (commonly abbreviated "heredoc"), and the string "EOF" can actually be any "word" you like.

The heredoc contains everything up to its matching delimiter, so nesting two heredocs is just a case of picking two different delimiters:

cat > terragrunt.hcl <<'ENDTERRAGRUNT' 
# Automatically generated from script $(basename $0)

# Generate the AWS provider block
generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<ENDROOTCONFIG
# Terragrunt root config
provider "aws" {
  # Only these AWS Account IDs may be operated on by this template
  allowed_account_ids = ["${local.account_id}"]
  region = "${local.infra_region}"
  version = "${local.customer_vars.locals.aws_provider_version}"
}
ENDROOTCONFIG
}

# Automatically generated from script $(basename $0)
ENDTERRAGRUNT
Related