正規表現

(ブログ記事の一覧は「こちら」)

正規表現とは「文字列の集合を一つの文字列で表現する方法の一つ」と説明されています。簡単に言うと、文字列があらかじめ決められたルールの文字で構成されているかどうかを意味します。正しい文字の組み合わせで構成されているかをチェックするときに利用するときに便利です。実際に例を見ながら学びましょう。

ここで学ぶこと

参考:

正規表現(PHPマニュアル)
preg_match 関数(PHPマニュアル)
preg_replace 関数(PHPマニュアル)

正規表現の基本構文

正規表現内で特別な働きをする文字を「メタ文字」と呼びます。ここではメタ文字の一部を紹介します。(より詳しく知りたい場合は、「正規表現」で検索するなどして調べてください。)

PHPでの正規表現は、スラッシュ「/」で囲んで記述します。(例. /abc+efg/)
以下に基本的な構文について取り上げます。

文字列の始まり/終わり
構文 説明
^ 文字列の始まり /^un/ →「un」で始まる文字列
$ 文字列の終わり /ing$/ →「ing」で終わる文字列
文字の構文
構文 説明
. 任意の1文字 /he..o/ →「hello」
[ ] 文字 /c[a-z]t/ →「cat」
\d 数字 [0-9] と同じ /Number\d/ →「Number8」
\s 空白文字(空白、改行、タブなど) /L\sR/ →「L R」
\w 英数字 /\w/ →「a」「B」「7」など
繰り返しの構文
構文 説明
? 直前の文字が0個か1個 /h[a-z]?ello/ →「hello」
* 直前の文字が0個以上の繰り返し /co*l/ →「cl」「cool」など
+ 直前の文字が1個以上の繰り返し /co+l/ →「col」「cool」など
{n} 直前の文字がn個 /d[a-z]{2}r/ →「door」「dear」など
{m,n} 直前の文字がm個以上n個以下 d[a-z]{2,4}g/ →「drag」「during」など
パターン修飾子
構文 説明
i 大文字と小文字を区別しない /abc/i →「ABc」「aBC」など
u 文字コードを「UTF-8」で扱う /こんにちは/u (日本語の場合は必須)
x パターン中の空白文字を無視する /a b c/x →「abc」

例題1

PHP正規表現によるマッチングを行う方法として、preg_match 関数の使い方を確認していきましょう。

$result = preg_match('/正規表現/', 検索する文字列);

$result は、検索する文字列が正規表現にマッチした場合は「1」、マッチしなかった場合は「0」を返します。

プログラム

郵便番号のルール(3文字の数字、ハイフン、4文字の数字)にマッチするかを確認するサンプルです。

<?php
    $pattern = '/^([0-9]{3})-([0-9]{4})$/';
// $pattern = '/^(\d{3})-(\d{4})$/';

    $zipcode1 = '115-0002';
    $zipcode2 = '220-601';

    $result1 = preg_match($pattern, $zipcode1);
    $result2 = preg_match($pattern, $zipcode2);

    var_dump($result1);
    var_dump($result2);
?>
int(1) int(0)


パターン修飾子を使用した、文字列のマッチングのサンプルです。

<?php
    // 大文字と小文字を区別しない
    $pattern = '/junichi/i';
    $str = 'Hello, I am Junichi.';
    $result = preg_match($pattern, $str);

    var_dump($result);

    // パターン中の空白文字を無視する
    $pattern = '/ab cd/x';
    $str = 'ab cd';
    $result = preg_match($pattern, $str);

    var_dump($result);
?>
int(1) int(0)


行の終わりが「でしょう。」になっているパターンを確認するサンプルです。

<?php
    $pattern = '/でしょう。$/u';

    $str1 = '今日は快晴です。';
    $str2 = '明日は曇りでしょう。';

    $result1 = preg_match($pattern, $str1);
    $result2 = preg_match($pattern, $str2);

    var_dump($result1);
    var_dump($result2);
?>
int(0) int(1)


年月日のルール(4文字の数字、スラッシュ、1〜2文字の数字、スラッシュ、1〜2文字の数字)にマッチするかを確認するサンプルです。 ただし、通常はスラッシュ「/」はメタ文字なので、文字列としての文字のスラッシュとして扱うには、エスケープ「\」を直前に加える必要があります。

<?php
    $pattern = '/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/u';

    $date1 = '2017/11/04';
    $date2 = '2017/3/8';
    $date3 = '2017年11月4日';

    $result1 = preg_match($pattern, $date1);
    $result2 = preg_match($pattern, $date2);
    $result3 = preg_match($pattern, $date3);

    var_dump($result1);
    var_dump($result2);
    var_dump($result3);
?>
int(1) int(1) int(0)

例題2

PHP正規表現に一致する文字列に置き換える方法として、preg_replace 関数の使い方を確認していきましょう。

$result = preg_replace('/正規表現/', 置き換える文字列, 対象の文字列);

$result は、対象の文字列を正規表現で置き換えた結果の文字列を返します。

以下は、句読点を取り除く例です。

<?php
    $str = '今日は、とても、良い天気です。明日は、曇りです。';

    $pattern1 = '/、/';
    $pattern2 = '/、|。/';

    $result1 = preg_replace($pattern1, '', $str);
    $result2 = preg_replace($pattern2, '', $str);

    var_dump($result1);
    var_dump($result2);
?>

実行、確認

string(63) "今日はとても良い天気です。明日は曇りです。"
string(57) "今日はとても良い天気です明日は曇りです"

課題1

「携帯電話番号」の正規表現を作成してください。
ルールは以下の通りとします。

  • 先頭は「0」
  • 数字のみの11文字
  • ハイフン「-」はあっても無くてもどちらでも良い

以下のサンプルを利用しても良いです。

<?php
    $pattern = '';      // 「携帯電話番号」の正規表現

    $num1 = '090-1234-5678';
    $num2 = '08012345678';
    $num3 = '070-1234-567';

    $result1 = preg_match($pattern, $num1);
    $result2 = preg_match($pattern, $num2);
    $result3 = preg_match($pattern, $num3);

    var_dump($result1);
    var_dump($result2);
    var_dump($result3);
?>

サンプルの出力は以下のようになります。

int(1) int(1) int(0)

課題2

フォームに入力した内容に間違いがないかどうかチェックすることを「バリデーション」と言います。

正規表現を利用して、「名前」「携帯電話番号」「メールアドレス」の入力フォームに対してバリデーションを行ってください。
全て正しい場合は、画面上に入力データを出力して、いずれかが間違っている場合は、「xxxが正しくありません」と出力してください。

「メールアドレス」の正規表現のルールは以下の通りとします。

  • 間のどこかに「@」を必ず含む
  • 「@」の左側は、英数字または「.」「-」「_」のいずれか
  • 「@」の右側は、英数字または「.」のいずれか
<?php
    if ($_SERVER ['REQUEST_METHOD'] == 'POST') {
        $name = $_POST['name'];
        $tel_number = $_POST['tel_number'];
        $email = $_POST['email'];

/*
       // 名前:未入力はエラー
       if () {
           echo($name . "<br>");
       } else {
           echo("名前が正しくありません" . "<br>");
       }

       // 携帯電話番号:正規表現でチェック
       if () {
           echo($tel_number . "<br>");
       } else {
           echo("電話番号が正しくありません" . "<br>");
       }

       // メールアドレス:正規表現でチェック
       if () {
           echo($email . "<br>");
       } else {
           echo("メールアドレスが正しくありません" . "<br>");
       }
*/
    }
?>

<html>
<head>
   <meta charset="UTF-8">
</head>

<body>
    <h1>データの送信チェック</h1>
    <form action="" method="POST">
        <p>名前:<input type="text" name="name"></p>
        <p>電話番号:<input type="text" name="tel_number"></p>
        <p>メールアドレス:<input type="text" name="email"></p>
        <input type="submit" value="送信する">
    </form>
</body>
</html>