# Строковые функции HCL: format, join, replace, lower и другие _Основы Terraform · TerraformLab Knowledge Base_ **TL;DR:** В HCL функции для строк: format (как printf), join/split (массивы↔строки), replace (regex или текст), lower/upper/title (регистр), trimspace и trim*. Все pure, без побочных эффектов, удобны в locals. ## Где видны эти функции Любое HCL-выражение может вызывать функцию: внутри `resource`, `data`, `variable.default`, `locals`, `output`. Синтаксис обычный: `func(arg1, arg2)`. Все строковые функции **чистые**, не делают сетевых запросов, не пишут на диск, выполняются на этапе plan. Это значит, их можно класть в любые выражения без побочных эффектов. ## `format`, как printf Шаблон + аргументы. Возвращает форматированную строку. ```hcl format("user-%s-%03d", "alice", 7) # "user-alice-007" format("%.2f USD", 19.999) # "19.99 USD" format("https://%s:%d", "api.example", 8080) # "https://api.example:8080" ``` Полезные модификаторы: - `%s`, строка - `%d`, целое число - `%f`, `%.2f`, float, два знака после точки - `%t`, bool - `%v`, что угодно (как есть) Есть ещё `formatlist`, применяет format к массиву: ```hcl formatlist("https://%s.example.com", ["api", "www", "admin"]) # ["https://api.example.com", "https://www.example.com", "https://admin.example.com"] ``` ## `join` и `split` Превращение массива в строку и обратно. ```hcl join(", ", ["a", "b", "c"]) # "a, b, c" join("/", ["my", "bucket", "path"]) # "my/bucket/path" split(",", "us-east-1,us-east-2,eu-central-1") # ["us-east-1", "us-east-2", "eu-central-1"] ``` Типичный кейс, собрать список CIDR'ов в строку для description: ```hcl description = "Allowed: ${join(", ", var.cidrs)}" ``` ## `replace`, подстрока или regex Две формы. По умолчанию, подстрока: ```hcl replace("hello-world", "-", "_") # "hello_world" ``` С regex, поиск/замена паттерна. Признак regex, символ `/` в начале и конце: ```hcl replace("v1.2.3-rc.4", "/-rc\\.\\d+$/", "") # "v1.2.3" replace("ARN-12345-XXX", "/[0-9]+/", "###") # "ARN-###-XXX" ``` Группы захвата с `$N`: ```hcl replace("user@example.com", "/^(.+)@(.+)$/", "$1 at $2") # "user at example.com" ``` Если regex невалидный, `terraform validate` упадёт с сообщением. Сначала отлаживайте в `terraform console`. ## `regex` и `regexall` Достать совпадение, а не заменять: ```hcl regex("[0-9]+", "version-42-build-7") # "42", первое совпадение regexall("[0-9]+", "version-42-build-7") # ["42", "7"], все ``` Полезно когда нужно вытащить число из имени ресурса или AMI. ## `lower`, `upper`, `title` ```hcl lower("AWS") # "aws" upper("us-east-1") # "US-EAST-1" title("hello world") # "Hello World" ``` Частый случай, нормализация имён ресурсов: ```hcl bucket = lower("${var.project}-${var.env}-${random_id.suffix.hex}") # AWS не любит верхний регистр в bucket names ``` ## `trim` и его варианты Убрать символы из начала/конца: ```hcl trimspace(" hello ") # "hello" , пробелы и переводы строк trim("xxxhelloxxx", "x") # "hello" , символы x с обеих сторон trimprefix("https://api.example", "https://") # "api.example" trimsuffix("logs.json", ".json") # "logs" ``` ## `substr`, подстрока ```hcl substr("hello world", 0, 5) # "hello" substr("abc-12345", 4, 5) # "12345" ``` Третий аргумент, длина, не индекс конца. ## `length` для строки Хоть `length` обычно про коллекции, для строки он считает **символы** (не байты!): ```hcl length("hello") # 5 length("привет") # 6 ``` Это важно при работе с UTF-8 ограничениями AWS (bucket name 3-63 символов). ## Конкатенация: лучше interpolation, чем `+` В HCL нет оператора `+` для строк. Используйте interpolation: ```hcl # Так не работает: # "hello" + "world" # Так, да: "${var.a}-${var.b}" ``` Если конкатенация сложная, выносите в `locals` (см. [tf-locals](/terraform/kb/tf-locals.md)). ## Подводные камни - **`format` строгий по типу.** `format("%d", "42")` упадёт, `"42"` это string, нужен `format("%s", "42")` или `parseint("42", 10)`. - **regex backslash экранируется дважды.** В `"/\\d+/"`, это паттерн `\d+`. Один `\` HCL съест как escape-символ строки. - **`replace` без `/.../`, это подстрока.** `replace("a.b", ".", "/")` заменит точку, не «любой символ». Для regex обязательны слеши: `replace("a.b", "/./", "/")`. - **`upper` и `lower` не работают на массивах.** `lower(["A", "B"])` упадёт. Используйте `[for s in arr : lower(s)]` (см. [tf-functions-collection](/terraform/kb/tf-functions-collection.md)). - **`title`, наивный.** `title("hello WORLD")` → `"Hello World"`. Каждое слово получает заглавную, остальное, нижний регистр. Для имён собственных может не подойти. - **`length` строки в символах, не байтах.** На многобайтовых строках может удивить. Если нужны байты, конвертация через `base64encode`+`length` (грубый хак). - **format/printf-like не интерполирует HCL-выражения.** `format("%s", var.x)` ок. `format("Hello, ${var.name}")`, лишнее, выражение можно просто `"Hello, ${var.name}"`. ## Команды ```bash terraform console ``` Главный инструмент для отладки строковых функций. Введи `format("%s-%d", "a", 1)` и получи результат. ```bash echo 'regex("[0-9]+", "abc-42")' | terraform console ``` Не-интерактивно проверить функцию из shell. ```bash terraform validate ``` Если в HCL невалидный regex или неправильный аргумент функции: validate упадёт без обращения к облаку. ## См. также - [Функции коллекций HCL: length, lookup, merge, concat, flatten](/terraform/kb/tf-functions-collection.md) - [${...}: подстановка значений в строки](/terraform/kb/tf-interpolation.md) - [locals: вычисляемые внутренние имена](/terraform/kb/tf-locals.md) - [Условия и null-safety: ?:, try, can, coalesce](/terraform/kb/tf-conditional-expression.md)