Terraform – FotD – replace()

This is part of an ongoing series of posts documenting the built-in interpolation functions in Terraform. For more information, check out the beginning post. In this post I am going to cover the replace() function. The example file is on GitHub here.

What is it?

Function name: replace(string, search, replace)

Returns: Takes a string and matches instances in the search value and replaces them with the replace value. Returns the updated string. The search value supports regular expressions if the value is bounded by the forward slash ‘/’.

Example:

# Returns bar
output "replace_output" {
  value = "${replace("foo","foo","bar")}"
}

Example file:

##############################################
# Function: replace
##############################################
##############################################
# Variables
##############################################
variable "source" {
  default = "Arthur scratched his head and discovered an Arthur doppelganger. Ford screamed and threw a towel over his head."
}

variable "search" {}

variable "replace" {}

##############################################
# Resources
##############################################


##############################################
# Outputs
##############################################
output "1_replace_basic" {
  value = "${replace(var.source,var.search,var.replace)}"
}

output "2_replace_long_hostname" {
  value = "${replace("heart-of-gold-42","/^(.)[^-]+-(.)[^-]+-(.)[^-]+-(\\d+)$/","$1$2$3$4")}"
}

output "3_replace_arthur" {
  value = "${replace(var.source,"/^(A\\S+)\\s.*$/","$1 stands alone.")}"
}

Run the following from the replace folder to get example output for a number of different cases:

#Standard replace
terraform apply -var "search=Arthur" -var "replace=Zaphod"

#Regex replace with or
terraform apply -var "search=/Arthur|Ford/" -var "replace=Zaphod"

#Empty replace is fine
terraform apply -var "search=/Arthur|Ford/" -var "replace="

#Emtpy search matches all characters except whitespace 
terraform apply -var "search=" -var "replace=42"

Why use it?

Replace is a pretty critical function if you’re planning to do any text string manipulation. You might use it to replace region names, hostnames, domain names, heck anything you want really. This does not work on lists or maps, so you would need to iterate through a list using the element function and a count loop. Same thing for map values, except first you’d need to use the values function to get a list of values.

Lessons Learned

The regex functionality is not well explained by the documentation. I guess either you’re super familiar with regex or you’re not, and the Terraform docs are not there to teach regex anyhow. For starters, you need to add the forward slash to the search string, e.g. /foo/ will match foo. You also need to double escape any backslashes as usual with Terraform, so the whitespace special character is \\s. The use of capture groups is also supported. Let’s say I have the string "foo man chu" and I use the regular expression /(foo).*/. That matches foo followed by 0 or more characters. The captured value of foo will be captured and stored in the placeholder $1. In the replace field you can put $1 bar and since the regular expression matches the entire source string, the replace value will replace all of the string. Since foo is captured in $1, the resulting string will be foo bar. Why would you use this? A quick Google search pointed out a situation where a person was trying to shorten the location names in AWS to be prepended to a hostname. I am sure there are other occasions where this would be useful. The syntax for the regular expressions is based on this GitHub project. You can also test your regular expressions, including capture groups, with this handy website. I also learned that if you submit an empty search string, the function will prepend the replace value to each non-whitespace character in the source string. That might actually be useful in some universe. Otherwise it just leads to really wacky behavior that will be “fun” to debug.

Coming up next is the rsadecrypt() function.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.