技術資料

PHPの正規表現で日本語・改行を扱う:u・m・s修飾子の違い

作成日:2026.09.29

PHPの正規表現で日本語や複数行テキストを扱う際の、u・m・s修飾子の違いを解説します。Unicode文字クラスと全角数字、CRLFの行末処理、\A・\zの使い方、Unicode正規化との違いを、PHP 8.3.15・PCRE2 10.42で確認したコード例とともに紹介します。

PHPで日本語を含む文字列に正規表現を使うときは、u修飾子を付けるだけでなく、改行や文字クラスがどう扱われるかも確認しておきたいところです。

この記事では、PHPの正規表現でよく使うu、m、s修飾子の違いを、短い例で整理します。PHP 8.3.15、PCRE2 10.42でコードを確認しています。

uはパターンと文字列をUTF-8として扱う

PHPの正規表現で日本語を扱う場合は、パターンの末尾にuを付けます。uを付けない場合、正規表現はUTF-8の日本語を複数のバイトとして扱います。次の例では、.が1文字分に一致するかを比べています。

$subject = '辰';

var_dump(preg_match('/\A.\z/', $subject));   // int(0)
var_dump(preg_match('/\A.\z/u', $subject));  // int(1)

\Aは対象文字列全体の先頭、\zは対象文字列全体の末尾を表します。^と$とは異なり、mを付けても各行の先頭・末尾には切り替わりません。この例では、その間にある.が文字列全体に一致するかを確認しています。UTF-8では「辰」は複数バイトで表現されるため、uがない.は1バイトだけに一致し、全体の末尾まで届きません。uを付けるとUTF-8として処理され、1文字に一致します。

uを使うときは、パターンと対象文字列が正しいUTF-8であることも前提になります。不正なUTF-8を渡すと、PHP 8.3.15ではpreg_matchがfalseを返し、preg_last_error_msg()でエラー内容を確認できます。文字列全体の形式を確認する場合は、複数行モードの影響を受けない\Aと\zで囲むと意図が明確です。

Unicodeの文字クラスと全角・半角を確認する

日本語の文字を含む条件を表すには、Unicodeプロパティを使う方法があります。例えば\p{L}はUnicode上の文字に一致します。

$subject = '漢字ABC';
$result = preg_match('/\A\p{L}+\z/u', $subject);

var_dump($result); // int(1)

数字については、半角数字だけを許可するのか、全角数字も許可するのかを決めておく必要があります。PHP 8.3.15では、uを付けた\dがUnicodeの数字にも一致します。半角数字だけに限定したい場合は、[0-9]のように許可する範囲を明記できます。

$subject = '123';

var_dump(preg_match('/\A\d+\z/u', $subject));     // int(1)
var_dump(preg_match('/\A[0-9]+\z/u', $subject));  // int(0)

これはPHPの実装がuの処理でPCRE2のUTFモードとUnicode文字プロパティを有効にしているためです。PCRE2単体の既定値とPHPから使う場合の挙動は同じとは限らないので、対象とするPHPのバージョンで確認しましょう。

また、正規表現はUnicodeの正規化を自動では行いません。例えば「が」は、U+304Cの1コードポイントで表す方法のほか、「か」(U+304B)に結合濁点(U+3099)を続けて表す方法もあります。どちらも「が」と表示されますが、文字列としては別の並びです。そのため、/\Aが\z/uは後者には一致しません。同じ文字として扱いたい場合は、入力をどの形式にそろえるかを決め、必要に応じてintl拡張のNormalizer::normalizeなどで正規化してから比較します。

mは行頭・行末、sはドットの範囲を変える

  • m: ^と$を文字列全体の先頭・末尾だけでなく、各行の先頭・末尾にも一致させる
  • s: .を改行にも一致させる

例えば、次の文字列ではmを付けると2行目だけを^と$で探せます。一方、文字列全体を.でまたいで検索するにはsを付けます。

$subject = "PHP\n正規表現";

var_dump(preg_match('/^正規表現$/mu', $subject));       // int(1)
var_dump(preg_match('/\APHP.正規表現\z/su', $subject)); // int(1)

mを付けても、.が改行に一致するわけではありません。逆に、sを付けても^と$が各行に一致するわけではありません。対象が1行の値か、複数行の文章かを考えて使い分けます。

CRLFでは行末にキャリッジリターンが残ることがある

Windowsでよく使われるCRLFは、\rと\nの2文字で改行を表します。PCRE2の改行規則がLFの場合、mの$は\nの直前に一致します。そのため、.で行の内容を取得すると、その直前の\rまで含まれることがあります。

$text = "first\r\nsecond";
preg_match_all('/^(.+)$/m', $text, $matches);

var_dump(bin2hex($matches[1][0])); // string(12) "66697273740d"

16進数の末尾にある0dが\rです。行単位のデータを処理する場合は、改行を正規表現で分割する方法もあります。PCRE2の\RはCRLFを含む改行シーケンスに一致します。

$text = "first\r\nsecond\nthird";
$lines = preg_split('/\R/u', $text);

var_export($lines);
// array ( 0 => 'first', 1 => 'second', 2 => 'third' )

末尾が改行で終わる文字列を分割すると、最後に空の要素ができる場合があります。空行をデータとして扱うかどうかに応じて、分割後の処理を決めてください。

入力条件に合わせてパターンを決める

日本語を含む文字列や複数行の入力を扱うときは、まず対象文字列の文字コードと改行形式を確認します。そのうえで、文字列全体を検証するのか、各行を検証するのか、改行をまたいで検索するのかを決めると、必要な修飾子を選びやすくなります。

  • UTF-8の日本語を扱う場合は、uを付けて入力文字列も確認する
  • 各行の先頭・末尾にアンカーを一致させる場合はmを使う
  • .で改行をまたぎたい場合はsを使う
  • 半角数字だけなど、許可範囲を限定する場合は[0-9]のように明記する
  • Unicode正規化や入力長の制限は、正規表現とは別の要件として決める

入力が長い場合や複雑なパターンを使う場合は、処理時間にも注意が必要です。利用者入力の長さに上限を設け、複雑なパターンを実データに近い文字列で確認してから使いましょう。

参考資料

この記事を書いた人

※上が私です。

奈良市を拠点に、27年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。

これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。

【制作会社・企業様向けサポート】
  • 専任エンジニアのいない企業様に対するシステム面の不安を解消
  • 柔軟な契約形態や短納期での対応により、急なニーズにも迅速にサポート
  • システムの企画段階から運用まで、ワンストップでのサービスを提供

Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。

ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。

PHPの正規表現を使い分ける:preg_match・preg_match_all・preg_replaceと入力検証

2026.08.28

PHPのpreg_match、preg_match_all、preg_replaceを使い、一致した値の取り出し、複数箇所の抽出、文字列置換を行う方法を解説します。u修飾子やmb_check_encodingにも触れ、メールアドレスの形式検証では、正規表現やfilter_var()だけで到達性・所有確認まではできないことを説明します。

PHP 正規表現

perlとPHPで使える、フォーム入力のエラーチェックに役立つ正規表現集

2009.03.28

フォームからのデータ送信はWebアプリケーションの基礎ですが、ユーザーが入力する内容が想定通りであるかを確認するためのエラーチェックは重要です。この記事では、perlとPHPでフォームデータをバリデートするための正規表現を具体例とともに紹介します。

Perl PHP 正規表現

Laravelのコードレビューで遅いSQLの候補を洗い出す

2026.10.02

Laravelのコードレビューで、ループ内のDBアクセスやEloquentのN+1、大量取得、検索条件とインデックスなど、性能問題につながりやすい箇所を候補として洗い出します。Laravelで発行SQLと実行時間を確認し、MySQLのEXPLAINや実データに近い環境での計測へつなげる方法を紹介します。コードレビューだけではSQLの実行時間を断定できない点も説明します。

Laravel MySQL PHP

Windows 11でDocker Composeを使ってLaravel環境を作る:Container・Volume・Networkの基本

2026.10.01

Windows 11のDocker Desktop上に、DockerfileとDocker Composeを使ってLaravel・PHP・MySQL・Mailpitの開発環境を構築します。ImageとContainerの関係、Bind MountとNamed Volumeによるデータの保存、ポート公開とContainer間通信の違いを実例で確認。LaravelからMySQLへ接続するときに、localhostではなくService名を使う理由も説明します。

Docker Laravel PHP

阿部辰也へのお仕事の依頼・お問い合わせ

軽いご相談もお気軽にどうぞ!

個人情報の取り扱いについて *必須 プライバシーポリシーをご確認いただき、同意いただける場合は「同意する」にチェックをしてください。

keyboard_double_arrow_up
TOP