startswith / endswith / regex / regexall — 文字列マッチング関数

1. 概要

  • startswith / endswith — 文字列の先頭・末尾を確認
  • regex — 正規表現でマッチした部分を抽出
  • regexall — 正規表現ですべてのマッチを取得
  • 実際のユースケース

Terraformの文字列マッチング関数は、変数値のバリデーション・条件分岐・文字列からのデータ抽出に使います。


2. startswith / endswith

startswith(string, prefix)は文字列が指定したプレフィックスで始まるかをboolで返します。endswith(string, suffix)は末尾を確認します。

# terraform consoleで確認
> startswith("dev-myapp", "dev-")
true

> startswith("prd-myapp", "dev-")
false

> endswith("myapp.tf", ".tf")
true

> endswith("myapp.tfvars", ".tf")
false

バリデーションでの活用

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

variable "bucket_name" {
  description = "S3バケット名(環境プレフィックス必須)"
  type        = string

  validation {
    # 環境名プレフィックスで始まることを強制
    condition     = startswith(var.bucket_name, "${var.environment}-")
    error_message = "バケット名は '${var.environment}-' で始まる必要があります。"
  }
}

variable "log_prefix" {
  description = "ログプレフィックス(末尾スラッシュ必須)"
  type        = string
  default     = "logs/"

  validation {
    condition     = endswith(var.log_prefix, "/")
    error_message = "ログプレフィックスは '/' で終わる必要があります。"
  }
}

resource "aws_s3_bucket" "app" {
  bucket = var.bucket_name

  tags = {
    Name        = var.bucket_name
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

### 条件分岐での活用

locals {
  # prod環境かどうかをstartswithで判定
  is_production = startswith(var.environment, "prd")
  instance_type = local.is_production ? "t3.medium" : "t3.micro"
}

3. regex — 正規表現でマッチを抽出

regex(pattern, string)は正規表現パターンにマッチした部分を返します。マッチしない場合はエラーになります。キャプチャグループがある場合はリストで返します。

# terraform consoleで確認
> regex("[0-9]+", "abc123def456")
"123"

# キャプチャグループ付き
> regex("([a-z]+)-([0-9]+)", "myapp-42")
["myapp", "42"]

# 名前付きキャプチャグループ
> regex("(?P<name>[a-z]+)-(?P<version>[0-9]+)", "myapp-42")
{"name": "myapp", "version": "42"}

AMI IDからリージョンを抽出する

locals {
  # AMI ARNからリージョン部分を抽出
  # arn:aws:ec2:ap-northeast-1::image/ami-xxx
  ami_arn    = "arn:aws:ec2:ap-northeast-1::image/ami-0123456789abcdef0"
  region     = regex("arn:aws:ec2:([^:]+):", local.ami_arn)[0]
  # → "ap-northeast-1"
}

4. regexall — すべてのマッチを取得

regexall(pattern, string)は正規表現にマッチしたすべての部分をリストで返します。マッチしない場合は空リストを返します(regexと異なりエラーにならない)。

# terraform consoleで確認
> regexall("[0-9]+", "abc123def456")
["123", "456"]

> regexall("[0-9]+", "no numbers here")
[]

# マッチしたかどうかの確認(length > 0でチェック)
> length(regexall("[0-9]+", "abc123")) > 0
true

CIDRブロックの抽出

locals {
  # 設定文字列からCIDRブロックを抽出
  config_text = "allowed: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16"
  cidr_blocks = regexall("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+", local.config_text)
  # → ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
}

5. 比較表

関数戻り値マッチしない場合ユースケース
startswith(str, prefix)boolfalseバリデーション・条件分岐
endswith(str, suffix)boolfalseバリデーション・条件分岐
regex(pattern, str)string/list/mapエラー文字列からデータ抽出
regexall(pattern, str)list空リスト複数マッチの取得

6. 関連記事


7. まとめ

  • startswith(str, prefix) — プレフィックスのチェック。バリデーションや条件分岐に使う
  • endswith(str, suffix) — サフィックスのチェック
  • regex(pattern, str) — 最初のマッチを返す。マッチしないとエラー
  • regexall(pattern, str) — すべてのマッチをリストで返す。マッチなしは空リスト
  • キャプチャグループはregex()でリスト/mapとして取得できる

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/startswith