Perlプログラミング入門ゼミ

Perlでテキスト処理、Linuxサーバー管理、Webシステム開発
  1. Perl
  2. 正規表現
  3. here

正規表現の文字クラス

複数の文字の集合を表現するには文字クラスを使用します。

[文字の集合]

たとえば「a」か「b」か「c」という文字を表現したい場合は[abc]と書きます。

a
b    ->    [abc]
c

アルファベットの範囲や数値の範囲を指定するのにハイフン「-」記号を使用することができます。

a
b
c    ->    [a-e]
d
e
0
1
2    ->    [0-4]
3
4

アルファベットと数値のいずれかを表現したい場合は[a-zA-Z0-9]と書きます。

アルファベットと数字    ->    [a-zA-Z0-9]

文字クラスの否定

文字クラスを使って特定の文字以外を表現することもできます。特定の文字以外を表現するには「^」を使用します。文字クラス[]の先頭で「^」が使用されると「それ以外」という意味になり、「文字の先頭」という意味にはならないので注意してください。

たとえば「a」「b」「c」以外の文字を表現するには次のようにします。

「a」「b」「c」以外の文字    ->    [^abc]

Perlで定義済みの文字クラス

Perlで定義済みの文字クラスというものが存在します。「\d」というのは、定義済みの文字クラスです。

文字クラス - 正規表現のリファレンスから、定義済みの文字クラスを引用します。

   \d      数値
   \D      非数値
   \w      単語文字
   \W      非単語文字
   \s      空白文字
   \S      非空白文字
   \h      水平空白文字
   \H      非水平空白文字
   \N      非改行 ('{NAME}' に引き続いていない場合; 実験的; 文字クラスでは
           不正; [^\n] と等価; /s なしの場合の '.' と同様)
   \v      垂直空白文字
   \V      非垂直空白文字
   \R      一般的な改行                (?>\v|\x0D\x0A)
   \C      1 バイトにマッチする (Unicode では、'.' は文字にマッチする)
   \pP     P の名前の (Unicode) プロパティ
   \p{...} 1 文字より長い名前の Unicode プロパティにマッチする
   \PP     非 P にマッチする
   \P{...} 1 文字より長い名前の Unicode プロパティがないものにマッチする
   \X      Unicode の拡張書記素クラスタにマッチする

文字クラスは、文字クラスの中でも使用できます。

[a-c\d\s]

注意してほしいのは、これらは、すべて、Unicodeの影響を受けるということです。PerlはUnicodeをサポートしており、日本語を扱うよい慣習は、プログラムの中では、すべて内部文字列(デコードされた文字列)として扱うことです。

この場合、「\d」は半角の0~9だけではなく、全角の0~9にもマッチします。\sは、半角の空白文字だけではなく、全角の空白文字にもマッチします。

ASCII範囲に限定したい場合は、以下の解説を読んでください。

文字クラスをASCII範囲のみに限定する

文字クラスをASCII範囲のみに限定する「a」オプションがPerl 5.14から導入されています。

# ASCII範囲の数字のみにマッチさせる。
$str =~ /\d+/a;

ASCII範囲のみを表現する文字クラス

Perlには、ASCIIの範囲を表現する文字クラスも存在します。この方法も、ASCII範囲のみに限定したい場合の、もう一つの解決方法です。

たとえばASCIIの範囲で、アルファベットと数字にマッチする文字クラスは以下のように表現できます。

# ASCIIの範囲で、アルファベットと数字にマッチする文字クラス
\p{PosixAlnum}

文字クラス - 正規表現のリファレンスから、定義済みの文字クラスを引用します。

ASCII-rangeと書かれている列の文字クラスに、注目してみましょう。

            ASCII-         Full-
   POSIX    range          range    backslash
 [[:...:]]  \p{...}        \p{...}   sequence    Description
 -----------------------------------------------------------------------
 alnum   PosixAlnum       XPosixAlnum            Alpha と Digit
 alpha   PosixAlpha       XPosixAlpha            英字
 ascii   ASCII                                   任意の ASCII 文字
 blank   PosixBlank       XPosixBlank   \h       水平空白;
                                                   全種類は \p{HorizSpace}
                                                   とも (GNU 拡張)
 cntrl   PosixCntrl       XPosixCntrl            制御文字
 digit   PosixDigit       XPosixDigit   \d       数字
 graph   PosixGraph       XPosixGraph            Alnum と Punct
 lower   PosixLower       XPosixLower            小文字
 print   PosixPrint       XPosixPrint            Graph と Print、しかし
                                                   Cntrl は含まない
 punct   PosixPunct       XPosixPunct            ASCII の範囲の句読点と
                                                   シンボル; 単にその外側の
                                                   punct
 space   PosixSpace       XPosixSpace            [\s\cK]
         PerlSpace        XPerlSpace    \s       Perl の空白の定義
 upper   PosixUpper       XPosixUpper            大文字
 word    PosixWord        XPosixWord    \w       Alnum + Unicode マーク +
                                                   '_' のような接続文字
                                                   (Perl 拡張)
 xdigit  ASCII_Hex_Digit  XPosixDigit            16 進数;
                                                    ASCII の範囲では
                                                    [0-9A-Fa-f]

文字クラスのサンプル

文字クラスのサンプルです。Webサイトの会員登録にも使える、ユーザーIDの正規表現、Webサービスのパスワードの正規表現のサンプルも書いてみました。

use strict;
use warnings;
use utf8;

# 文字クラスを使う
my $str = 'Hello';
if ($str =~ /[abcde]/) {
  print "Match\n";
}

# WebサービスのユーザーID(a-zA-Z0-9_)にマッチさせる
my $user_id = 'kimoto_yuki089';
my $user_id_invalid = 'abc&cde';
if ($user_id =~ /^\p{PosixWord}+$/) {
  print "user_is valid\n";
}
unless ($user_id_invalid =~ /^\p{PosixWord}+$/) {
  print "user_id_invalid is invalid\n";
}

# Webサービスのパスワード(ASCII範囲の空白以外の見える文字)にマッチさせる
my $password = 'Ufy|&123_';
my $passowrd_invalid1 = 'abc def';
my $passowrd_invalid2 = 'abcあ';
if ($password =~ /^\p{PosixGraph}+$/) {
  print "password is valid\n";
}
unless ($passowrd_invalid1 =~ /^\p{PosixGraph}+$/) {
  print "passowrd_invalid1 is inalid\n";
}
unless ($passowrd_invalid2 =~ /^\p{PosixGraph}+$/) {
  print "passowrd_invalid2 is inalid\n";
}