できない.dev

文字列が正規表現に一致するか調べるには

文字列がパターンに当てはまるかどうかを真偽値で受け取る基本形を各言語で示す。
「先頭からの一致」「どこかに含まれる」「全体が一致」の 3 つが言語ごとに別のメソッドに割り当てられている点までを扱う。

公開:

各言語見出しの横のバッジは検証状態を表す。実行確認済みはコードを実際に実行して確認したもの、静的確認は構文と公式 API ドキュメントで確認したものである。

Python 実行確認済み

import re
 
text = "order-2026-08-31"
pattern = r"^order-\d{4}-\d{2}-\d{2}$"
 
print(bool(re.match(pattern, text)))          # True(先頭から照合する)
print(bool(re.search(r"\d{4}", text)))        # True(どこかにあれば True)
print(bool(re.match(r"\d{4}", text)))         # False(match は先頭しか見ない)
print(bool(re.fullmatch(r"order-.+", text)))  # True(全体が一致するか)

re.match は先頭からの一致、re.search はどこかにあるか、re.fullmatch は全体一致をそれぞれ判定する。
「含まれるか」を調べたいのに re.match を使うのがもっとも多い取り違えなので、目的に合うものを選ぶ。
戻り値は Match オブジェクトか None なので、真偽値が欲しいときは bool で包む。

JavaScript 実行確認済み

const text = "order-2026-08-31";
const pattern = /^order-\d{4}-\d{2}-\d{2}$/;
 
console.log(pattern.test(text)); // true
console.log(/\d{4}/.test(text)); // true(部分一致)
 
// g 付きの正規表現は lastIndex を持ち回るので、同じ値でも 2 回目が false になる
const global = /order/g;
console.log(global.test(text), global.test(text)); // true false

RegExp.prototype.test は真偽値をそのまま返すため、一致の有無だけを見たいときはこれが最短である。
ただし g フラグを付けた正規表現は lastIndex を保持し、同じインスタンスで test を繰り返すと途中から探し始めるので、判定用のパターンには g を付けない。

TypeScript 実行確認済み

const text: string = "order-2026-08-31";
const pattern: RegExp = /^order-\d{4}-\d{2}-\d{2}$/;
 
const isOrderId: boolean = pattern.test(text);
console.log(isOrderId); // true
 
// match の戻り値は RegExpMatchArray | null なので、null を外してから使う
const found: RegExpMatchArray | null = text.match(/\d{4}/);
console.log(found !== null ? found[0] : "no match"); // 2026

test の戻り値は boolean なので、そのまま条件式に使える。
一方で match の戻り値は RegExpMatchArray | null であり、null を外さないと要素へアクセスできない。
判定だけなら test、値も要るなら match と使い分けると型の扱いが素直になる。

Go 静的確認

package main
 
import (
	"fmt"
	"regexp"
)
 
func main() {
	text := "order-2026-08-31"
	re := regexp.MustCompile(`^order-\d{4}-\d{2}-\d{2}$`)
	fmt.Println(re.MatchString(text)) // true
 
	// 使い捨てなら関数版もあるが、こちらはコンパイル失敗を error で返す
	ok, err := regexp.MatchString(`\d{4}`, text)
	fmt.Println(ok, err) // true <nil>
}

regexp.MustCompile はコンパイルに失敗するとパニックするので、リテラルで書いたパターンに使う。
実行時に組み立てたパターンなら regexp.Compile を使い、error を受け取って処理する。
バッククォート文字列にすると、バックスラッシュを二重に書かずに済む。

Rust 静的確認

use regex::Regex;
 
fn main() {
    let text = "order-2026-08-31";
    let re = Regex::new(r"^order-\d{4}-\d{2}-\d{2}$").unwrap();
    println!("{}", re.is_match(text)); // true
 
    // 部分一致でよければアンカーを外す
    println!("{}", Regex::new(r"\d{4}").unwrap().is_match(text)); // true
}

regex クレートを Cargo.toml の依存に追加してから使う。
Regex::new は Result を返すため、リテラルのパターンなら unwrap でよいが、外部入力から作る場合は失敗を扱う。
同じパターンを繰り返し使うときは、ループの外で 1 度だけ生成する。

Java 実行確認済み

import java.util.regex.Pattern;
 
public class RegexMatch {
    public static void main(String[] args) {
        String text = "order-2026-08-31";
        Pattern p = Pattern.compile("^order-\\d{4}-\\d{2}-\\d{2}$");
 
        System.out.println(p.matcher(text).matches()); // true(全体一致)
        System.out.println(p.matcher(text).find());    // true(部分一致)
        System.out.println(text.matches("\\d{4}"));    // false(String.matches も全体一致)
        System.out.println(Pattern.compile("\\d{4}").matcher(text).find()); // true
    }
}

Matcher.matches は文字列全体の一致、find は部分一致を判定する。
String.matches も全体一致なので、部分一致のつもりで使うと常に false になる。
同じパターンを使い回すなら、Pattern.compile の結果を定数として保持するとコンパイルが 1 度で済む。

C# 実行確認済み

using System.Text.RegularExpressions;
 
var text = "order-2026-08-31";
 
Console.WriteLine(Regex.IsMatch(text, @"^order-\d{4}-\d{2}-\d{2}$")); // True
Console.WriteLine(Regex.IsMatch(text, @"\d{4}"));                     // True(部分一致)
Console.WriteLine(Regex.IsMatch(text, @"^\d{4}$"));                   // False
 
// 同じパターンを繰り返し使うなら、コンパイル済みインスタンスを使い回す
var order = new Regex(@"^order-", RegexOptions.Compiled);
Console.WriteLine(order.IsMatch(text)); // True

Regex.IsMatch は真偽値を返す静的メソッドで、既定では部分一致を見る。
全体一致にしたいときは ^ と $ を明示する。
同じパターンを何度も使うなら RegexOptions.Compiled を付けた Regex インスタンスを使い回すと、毎回の解析を避けられる。

つまずき

同じ「一致」でも、先頭からなのか・どこかにあればよいのか・全体が一致するのかで使うメソッドが変わる。
Python の re.match と Java の String.matches はどちらも「match」という名前だが、前者は先頭からの一致、後者は全体一致であり意味が違う。
名前ではなく仕様で選ぶこと。

g フラグと状態

JavaScript の正規表現リテラルに g を付けると、その RegExp オブジェクトは lastIndex という状態を持つ。
判定に使い回すと 2 回目以降が前回の続きから始まり、同じ入力なのに結果が変わる。
判定用には g を付けず、全件の抽出が必要なときだけ g と matchAll を使う。

この記事は役立ちましたか?