Kotlinの正規表現の使い方について

採用はこちら

Kotlinでは、Javaの正規表現エンジン(java.util.regex)を基盤としながら、Kotlinらしい安全性と可読性を備えた Regex クラスが提供されています。

本記事では、「仕様として正しいこと」+「実務で事故らないこと」この2点を重視して、Kotlinの正規表現を基礎から丁寧に解説します。

目次

Kotlinで正規表現を扱う基本

Regexクラスを使う

Kotlinでは正規表現を Regex クラスとして扱います。

val regex = Regex("abc")
  • 内部的には Java の Pattern を使用
  • Kotlinコードでは Regex を使うのが基本かつ推奨

Javaの Pattern / Matcher を直接使う必要は、ほとんどのケースでありません。

マッチ判定の基本

完全一致:matches()

val regex = Regex("""\d+""")

regex.matches("123")   // true
regex.matches("123a")  // false

ポイント

  • matches()文字列全体が正規表現に一致した場合のみ true
  • 正規表現の ^...$ が暗黙的に付いていると考えると分かりやすい
  • 入力値バリデーションで多用される

部分一致の有無:containsMatchIn()

val regex = Regex("""\d+""")

regex.containsMatchIn("abc123def") // true
regex.containsMatchIn("abcdef")    // false

ポイント

  • 「1箇所でもマッチするか」を判定
  • ログ解析、検索処理、テキストスキャン向き

String.contains(Regex) との関係

"abc123def".contains(Regex("""\d+""")) // true

これは内部的に Regex.containsMatchIn() を呼んでおり、意味は完全に同じです。

  • regex.containsMatchIn(text) → 正規表現起点
  • text.contains(regex) → 文字列起点

どちらを使っても問題ありません。

コードの読みやすさで選ぶのがベストです。

マッチ結果の取得

最初の一致を取得:find()

val regex = Regex("""\d+""")
val match = regex.find("abc123def")

match?.value  // "123"
  • 見つからなければ null
  • Kotlinの null安全設計に自然に組み込める

すべての一致を取得:findAll()

val regex = Regex("""\d+""")

for (result in regex.findAll("a1b22c333")) {
    println(result.value)
}

出力

1
22
333

ポイント

  • findAll()Sequence<MatchResult> を返す
  • 遅延評価のため、大量テキストでも無駄なメモリ消費を抑えられる

Raw文字列(""" ... """)を使うべき理由

通常の文字列

Regex("\\d+")

Raw文字列:

Regex("""\d+""")

Raw文字列のメリット

  • バックスラッシュの二重エスケープが不要
  • 正規表現がそのまま読める
  • 修正時のミスが激減する

Kotlinで正規表現を書くなら、Raw文字列が事実上の標準

キャプチャグループの扱い方

番号付きキャプチャ

val regex = Regex("""(\d{4})-(\d{2})-(\d{2})""")
val match = regex.find("2026-02-17")

if (match != null) {
    match.groupValues[1] // "2026"
    match.groupValues[2] // "02"
    match.groupValues[3] // "17"
}

特徴

  • groupValues[0] は全体一致
  • JVM / Android / 古いKotlin環境でも確実に動作
  • 互換性・安全性を最優先するならこれ

名前付きキャプチャ(可読性重視)

val regex = Regex("""(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})""")
val match = regex.find("2026-02-17")

if (match != null) {
    match.groups["year"]?.value
    match.groups["month"]?.value
}

正確な整理

  • (?<name>...)Java互換の正規表現仕様
  • Kotlin/JVMの一般的な環境では
    match.groups["name"] で問題なく取得できる
  • ただし、
    • 非常に古いKotlin
    • Kotlin Multiplatform など一部ターゲット
      では差が出る可能性がある

環境が固定されていない場合は番号キャプチャが最も安全
可読性を優先できる場合は名前付きキャプチャが有効

置換処理(replace)

単純な置換

val text = "電話番号: 090-1234-5678"
val masked = text.replace(Regex("""\d"""), "*")

ラムダによる動的置換

val result = "価格: 1200円".replace(Regex("""\d+""")) {
    (it.value.toInt() * 1.1).toInt().toString()
}

ポイント

  • itMatchResult
  • マッチ内容に応じた柔軟な変換が可能
  • Kotlinの正規表現がJavaより使いやすい理由の一つ

よく使われる正規表現パターン

※以下は「フォーマット確認用途」の簡易例です
厳密な検証には専用APIやパーサの併用を推奨します

数値

\d+

英数字

[a-zA-Z0-9]+

メールアドレス(簡易)

[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}

URL(簡易)

https?://[\w/:%#\$&\?\(\)~\.=\+\-]+

日本の郵便番号

\d{3}-\d{4}

実務上の注意

  • メールやURLを 正規表現だけで完全検証するのは非推奨
  • 「それっぽい形式か」を見る一次チェック用途に限定する
  • 最終判断は URI / URL / 実通信などに委ねる

RegexOption(フラグ)の正しい理解

代表的なオプション

Regex(
    "abc",
    setOf(
        RegexOption.IGNORE_CASE,
        RegexOption.MULTILINE
    )
)

混同しやすいポイント

  • MULTILINE
    ^$ が「行単位」でマッチする
  • DOT_MATCHES_ALL
    . が改行文字も含むようになる

意味が全く違うので注意

パフォーマンスと設計の指針

Regexは使い回す

❌ 毎回生成

fun check(text: String) =
    Regex("""\d+""").containsMatchIn(text)

⭕ 使い回す

private val numberRegex = Regex("""\d+""")

fun check(text: String) =
    numberRegex.containsMatchIn(text)
  • Regex 生成には内部準備コストがある
  • ホットパスでは使い回しが基本

正規表現が不要なケースも多い

  • startsWith
  • endsWith
  • contains
  • split

単純な処理はString APIの方が速く、読みやすい

まとめ

  • Raw文字列(""")を使う
  • matches(全体一致)と containsMatchIn(部分一致)を正しく使い分ける
  • キャプチャは
    • 安全性重視 → 番号
    • 可読性重視 → 名前
  • Regexは使い回す
  • 正規表現に頼りすぎない

以上、Kotlinの正規表現の使い方についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次