Quick Answer
Terraform provides 20+ built-in string functions for formatting, splitting, joining, searching, and transforming text. The most commonly used are format, join, split, replace, lower, upper, trimspace, and regex.
Most Used String Functions
format / formatlist
# format — sprintf-style string formatting
output "name" {
value = format("web-%s-%02d", var.environment, 1)
# "web-prod-01"
}
# formatlist — format each item in a list
output "names" {
value = formatlist("web-%s-%02d", var.environment, [1, 2, 3])
# ["web-prod-01", "web-prod-02", "web-prod-03"]
}
join / split
# join — combine list into string
output "csv" {
value = join(",", ["a", "b", "c"])
# "a,b,c"
}
# split — break string into list
output "parts" {
value = split(",", "a,b,c")
# ["a", "b", "c"]
}
# Common pattern: create comma-separated security group IDs
output "sg_ids" {
value = join(",", aws_security_group.main[*].id)
}
replace
# Simple replacement
output "clean_name" {
value = replace("my_resource_name", "_", "-")
# "my-resource-name"
}
# Regex replacement (wrap pattern in forward slashes)
output "no_digits" {
value = replace("web-server-01", "/[0-9]+/", "XX")
# "web-server-XX"
}
lower / upper / title
output "lower" { value = lower("Hello World") } # "hello world"
output "upper" { value = upper("Hello World") } # "HELLO WORLD"
output "title" { value = title("hello world") } # "Hello World"
trim / trimprefix / trimsuffix / trimspace
output "trimmed" { value = trimspace(" hello ") } # "hello"
output "no_prefix" { value = trimprefix("arn:aws:s3:::bucket", "arn:aws:s3:::") } # "bucket"
output "no_suffix" { value = trimsuffix("server.example.com.", ".") } # "server.example.com"
output "trim_chars" { value = trim("?!hello?!", "?!") } # "hello"
substr
# substr(string, offset, length)
output "first_8" {
value = substr("us-east-1a", 0, 9)
# "us-east-1"
}
regex / regexall
# Extract first match
output "version" {
value = regex("v([0-9]+\\.[0-9]+)", "terraform-v1.5.7")
# ["1.5"]
}
# Extract all matches
output "numbers" {
value = regexall("[0-9]+", "web-01-app-02")
# ["01", "02"]
}
# Validate format
output "is_valid_cidr" {
value = can(regex("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+$", var.cidr))
}
startswith / endswith / contains / strcontains
output "is_prod" {
value = startswith(var.environment, "prod") # true/false
}
output "has_suffix" {
value = endswith(var.hostname, ".internal")
}
# strcontains (Terraform 1.5+)
output "is_aws" {
value = strcontains(var.provider_arn, "aws")
}
chomp / indent
# Remove trailing newline
output "clean" { value = chomp("hello\n") } # "hello"
# Indent multi-line string
output "indented" {
value = indent(4, "line1\nline2\nline3")
# "line1\n line2\n line3"
}
Real-World Examples
Generate Resource Names
locals {
name_prefix = lower(format("%s-%s", var.project, var.environment))
}
resource "aws_s3_bucket" "data" {
bucket = "${local.name_prefix}-data"
# "myapp-prod-data"
}
Parse ARNs
locals {
arn_parts = split(":", var.role_arn)
account_id = local.arn_parts[4]
role_name = trimprefix(local.arn_parts[5], "role/")
}
Clean User Input
locals {
clean_name = lower(trimspace(replace(var.user_input, "/[^a-zA-Z0-9-]/", "")))
}
Function Quick Reference
| Function | Purpose | Example |
|---|---|---|
format | Printf-style formatting | format("web-%s", var.env) |
join | List → string | join(",", list) |
split | String → list | split(",", string) |
replace | Find and replace | replace(s, "_", "-") |
lower | Lowercase | lower("ABC") → "abc" |
upper | Uppercase | upper("abc") → "ABC" |
trimspace | Strip whitespace | trimspace(" a ") → "a" |
substr | Substring | substr(s, 0, 5) |
regex | Regex extract | regex("[0-9]+", s) |
startswith | Prefix check | startswith(s, "prod") |
chomp | Remove trailing newline | chomp("a\n") → "a" |
Related Articles
Conclusion
String functions handle naming conventions, ARN parsing, input validation, and resource tagging. format + join + replace + lower cover 80% of use cases. Use regex for complex patterns and can(regex(...)) for validation.




