Chinaunix首页 | 论坛 | 博客
  • 博客访问: 100612
  • 博文数量: 20
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-06 11:04
文章分类

全部博文(20)

文章存档

2011年(1)

2010年(14)

2009年(4)

2008年(1)

我的朋友

分类:

2010-07-28 15:37:06

> 第7章 正規表現
  第7章 正規表現



7-1. パターンマッチ演算子

  • 正規表現とは、ある特定の文字列ではなく、文字列の一部をパターン化して表現する手法をいいます。
  • 複数行ある文章の中から文字列を検索する時に、検索したい文字列すべてを指定するのではなく、文字列の任意の一部を置き換え可能な状態 にして検索をする場合に正規表現を用います。たとえば、UNIXやWindowsでは、文字列を検索するときに使用される正規表現として、「*」を任意の 文字列(空き文字も含む)に、「?」を任意の1文字として使用することができます。 パターンを、app* と表現すると、 apple application appeal などの文字列がマッチすることになります。
  • この正規表現の方法は、当然ながらプログラム言語ごとに異なりますが、Perlの場合は他の言語に比べて非常に強力な正規表現によるパターンマッチ機能を備えており、より詳細にかつ容易にパターンマッチを行うことができるとされています。

  • Perlでは、パターンマッチ演算子として、スラッシュ ( / ) で囲んだ文字列が正規表現であるとされます。性格上、正規表現は条件式と併用して用いられることが多いようです。この場合次のような構文があります。

    構文 意味
    if ( 文字列 =~ /パターン/) もし「文字列」の中に「パターン」が含まれていれば
    (パターンマッチすれば
    if ( 文字列 !~ /パターン/) もし「文字列」の中に「パターン」が含まれていなければ
    (パターンマッチすれば


    $word = 'apple';
    if ($word =~ /a/) {
         print "
    含まれています。\n";
    } else {
         print "
    含まれていません。\n";
    }


    <出力結果>
    含まれています。


    また、上記構文(パターンマッチすれば)の省略形の位置づけとして、次の構文があります。この場合、対象となる「文字列」は特殊変数 $_ が充てられます。

    構文 意味
    if (/パターン/) もし変数 $_ の中に「パターン」が含まれていれば
    (パターンマッチすれば


    $_ = 'apple';
    if (/a/) {
         print "
    含まれています。\n";
    } else {
         print "
    含まれていません。\n";
    }


    <出力結果>
    含まれています。


    正規表現は通常スラッシュ ( / ) で囲んだ部分がパターンマッチの対象となりますが、このスラッシュを他の任意の記号に置き換えることもできます。
    パターンの中に「スラッシュ」が多く含まれる場合に、正規表現を書きやすくするための措置と思われます。

    構文 意味
    m 区切り文字 パターン 区切り文字 /パターン/ に同じ

    ※「区切り文字」とは、空白文字以外の記号を使用することができます。 (ex. @, #, *, | など)

    $url = '';
    if ($url =~ /http:
    \/\//) { print "含まれています。\n"; }

    ↓ 次のように記述することが可能。(エスケープしない分、書きやすくなる)

    $url = '';
    if ($url =~ m|http://|) { print "
    含まれています。\n"; }



  • パターンマッチ演算子には、正規表現を行う際のオプションとして、いくつかの修飾子が用意されています。

    修飾子 意味
    g 繰り返しマッチする
    i 大文字と小文字の区別をしない
    o 変数展開を1度だけ行う
    m 文字列を複数行として扱う
    s 文字列を単一行として扱う
    x 拡張正規表現を行う


    ▽g修飾子の例
    $word = 'ABCDEF';
    while ($word =~ /(.)/g){ push(@word, $1); }
    print "@word
    \n";

    <出力結果>
    A B C D E F
    (変数$wordから1文字づつマッチさせて配列@wordに格納する)

    ▽i修飾子の例
    ▽例文(1)
    $word = 'apple';
    if ($word =~ /A/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果(1)>
    マッチしません。

    ▽例文(2) : i修飾子を使う場合
    $word = 'apple';
    if ($word =~ /A/i) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果(2)>
    マッチします。

    ▽m修飾子の例
    ▽例文(3)
    $word = "AAA\nBBB\n";
    if ($word =~ /^B/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果(3)>
    マッチしません。

    ▽例文(4) : m修飾子を使う場合
    $word = "AAA\nBBB\n";
    if ($word =~ /^B/m) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果(4)>
    マッチします。




7-2. メタ文字
  • 正規表現を行ううえで、次のようなメタ文字と呼ばれる特殊な意味を持つ文字には、そのままではマッチできないため、必ず直前に \ を付加してエスケープする必要があります。

      \  ^   .   $   *   ?   |   (   )   [   ]   {   }  


    ▼メタ文字を「文字」としてマッチさせるためには、直前に \ を付ける
    $price = 'This is $100';
    if ($price =~ /
    \$/) {
         print "
    含まれています。\n";
    } else {
         print "
    含まれていません。\n";
    }


    <出力結果>
    含まれています。


    これらのメタ文字を正規表現の中で使用する場合については、次に解説していくことにします。

    1. 任意の1文字と位置指定

    メタ文字 正規表現上の意味
    \ 直後の文字をエスケープ
    ^ 先頭にマッチ
    . 改行を除く任意の1文字
    $ 末尾にマッチ


    ▼「 ^ 」(キャレット)の使用例
    $word = 'apple';
    if ($word =~ /^a/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果>
    マッチします。 (apple という文字列は a で始まるため)


    ▼「 . 」(ドット)の使用例
    $word = 'apple';
    if ($word =~ /app.e/) {
        print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果>
    マッチします。 (apple という文字列の l は改行以外の任意の1文字のため)


    ▼「 $ 」(ダラー)の使用例
    $word = 'apple';
    if ($word =~ /e$/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果>
    マッチします。 (apple という文字列の e は末尾にあるため)


    2. パターン論理和

    メタ文字 正規表現上の意味
    | 選択


    複数の文字列をパイプで分割すると、複数の文字列のどれかにマッチさせます。

    ▼「 | 」(パイプ)の使用例
    $word = 'apple';
    if ($word =~ /a|b|c/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果>
    マッチします。 (apple という文字列に a 又は b 又は c の文字があるため)


    3. パターングループ

    メタ文字 正規表現上の意味
    (   ) グループ化


    複数の文字列をまとめた形でパターンマッチを行います。
    またこのパターングループでマッチした文字列は、特殊変数 ( $ + 数字 ) に、マッチした順に代入することができます。( ex. $1, $2, $3, ... )

    ▼「 (   ) 」(バーレン)の使用例
    $word = 'apple';
    if ($word =~ /^(...)(.)(.)/) {
           print "
    先頭の3文字 $1 \n";
           print "
    次の1文字 $2 \n";
           print "
    次の1文字 $3 \n";
    }


    <出力結果>
    先頭の3文字 app
    次の1文字 l
    次の1文字 e


    4. 文字クラス

    メタ文字 正規表現上の意味
    [   ] 指定内の任意表現


    マッチングの対象となる文字列中に、[   ] (ブラケット)で囲んだ文字のいずれかをマッチさせるため表現です。
    このとき、ブラケット中の先頭部に、「 ^ 」(キャレット)があれば、逆の意味となり、「含まれていない」文字にマッチするという意味になります。
    また、ブラケット中に「 - 」(マイナス)があれば、範囲指定を意味します。

    ▼「 [   ] 」(ブラケット)の使用例
    $word = 'apple';

    if ($word =~ /[a-z]/) {
         print "
    英小文字が含まれています。\n";
    } else {
         print "
    英小文字は含まれていません。\n";
    }

    if ($word =~ /[0-9]/) {
         print "
    数字が含まれています。\n";
    } else {
         print "
    数字は含まれていません。\n";
    }


    <出力結果>
    英小文字が含まれています。
    数字は含まれていません。


    文字クラスで多用されるものとして、次のような表現があります。

    文字クラス 意味
    [a-z] 英小文字のいずれか1文字
    [A-Z] 英大文字のいずれか1文字
    [0-9] 数字1文字
    [a-zA-Z0-9] 英数字1文字
    [^a-zA-Z] 英字以外にマッチ
    [^0-9] 数字以外にマッチ


    5. 量指定子

    メタ文字 正規表現上の意味
    * 直前の文字を0回以上にマッチ
    + 直前の文字を1回以上にマッチ
    ? 直前の文字を0又は1回にマッチ
    {n} 直前の文字をn回にマッチ
    {n,} 直前の文字をn回以上にマッチ
    {n,m} 直前の文字をn回以上、m回以下にマッチ


    ▼「 {   } 」(ブレース)の使用例
    $word = 'apple';
    if ($word =~ /[a-z]{5}/) {
         print "
    マッチします。\n";
    } else {
         print "
    マッチしません。\n";
    }


    <出力結果>
    マッチします。 (apple という文字列に、英小文字が5回繰り返されているため)


    量指定子の正規表現を行う場合、マッチする範囲は最大マッチであることに注意しましょう。
    まず以下の例を見てみましょう。

    $word = 'apple:1 banana:3 orange:2';
    if ($word =~ /(.+[0-9])/) { print "$1
    \n"; }

    <出力結果>
    apple:1 banana:3 orange:2


    上記は「数字の前に1個以上の何らかの文字列」がある場合にマッチさせるパターンです。この場合、変数$wordの文字列はすべてマッチしてしまいます。要は、末尾の数字の2の前に1個以上の文字列があるためです。
    「数字の前に1個以上の何らかの文字列」という条件であれば、「apple:1」や「apple:1 banana:3」という文字列でもあてはまりますが、このように最大の範囲内で条件にあてはまる部分がマッチするという取り決めになっています。

    そこで、最短マッチにする場合のオプションとして、量指定子の直後に ? (クエスチョン) をつけることでそれが可能となります。

    $word = 'apple:1 banana:3 orange:2';
    if ($word =~ /(.+?[0-9])/) { print "$1
    \n"; }

    <出力結果>
    apple:1


    量指定子での最短マッチを行うパターンをまとめると次のようになります。

    *? 直前の文字を0回以上に最短マッチ
    +? 直前の文字を1回以上に最短マッチ
    ?? 直前の文字を0又は1回に最短マッチ
    {n}? 直前の文字をn回に最短マッチ
    {n,}? 直前の文字をn回以上に最短マッチ
    {n,m}? 直前の文字をn回以上、m回以下に最短マッチ


    6. その他のメタ文字及び特殊変数

    これまで説明したもの以外で、正規表現上の特殊な意味として用いられるものには次のようなものがあります。

    表現 正規表現上の意味
    \w 英字、数字、アンダースコア。[a-zA-Z0-9_] に同じ。
    \W 英字、数字、アンダースコア以外の文字。[^a-zA-Z0-9_] に同じ。
    \d 数字。[0-9] に同じ。
    \D 数字以外の文字。[^0-9] に同じ。
    \t タブ
    \r リターン(復帰文字)
    \n 改行
    \f ラインフィード(改ページ)
    \s スペース。[ \r\t\n\f] に同じ。
    \S スペース以外の文字。[^ \r\t\n\f] に同じ。
    \a アラーム(ベル)
    \d バックスペース
    \e エスケープ
    \0 + 数字 8進法で表すASCII文字。( ex. \033, \040 など )
    \x + 英数字 16進法で表すASCII文字。( ex. \x1b, \x00 など )
    \c[ コントロール文字
    \l 次の1文字を小文字にする
    \u 次の1文字を大文字にする
    \L \Eまでの文字列を小文字にする
    \U \Eまでの文字列を大文字にする
    \E 変更の終わり
    \Q \Eまでの文字列で正規表現のメタ文字を文字にみなす
    \b 単語の境界にマッチする
    \B 単語の境界以外にマッチする
    \A 文字列の最初にマッチする。メタ文字 ^ に同じ。
    \Z 文字列の最後にマッチする。メタ文字 $ に同じ。
    $ + 数字 グループ化したパターンを後で参照する。( ex. $1, $2, $3, ... )
    \ + 数字 上記に同じ。( ex. \1, \2, \3, ... )
    $& マッチした文字列全体
    $` マッチした文字列の前にあるすべての文字列
    $' マッチした文字列の後にあるすべての文字列




7-3. 置換演算子
  • 正規表現を使用し、マッチした文字列を置き換える置換演算子があります。

    構文 意味
    s/パターン/置換文字列/ 「パターン」にマッチする文字列を「置換文字列」に置き換える


    $word = "This is a pen.";
    $word =~ s/pen/book/;
    print "$word
    \n";

    <出力結果>
    This is a book.


    置換演算子は省略形として、左辺を省略することもできます。この場合、左辺は 特殊変数 $_ が充てられます。

    $_ = "This is a pen.";
    s/pen/book/;
    print "$_
    \n";

    <出力結果>
    This is a book.


    パターンを囲む区切り文字のスラッシュを、任意の区切り文字 (ex. @, #, *, | など)に変更することができます。この場合、パターンマッチ演算子とは異なり、先頭の mオプションを付けることはありません。

    $url = 'bbs/file/';
    $url =~ s/
    \/bbs\/file\//\/chat\/data\//;

    ↓ 次のように記述することが可能。(エスケープしない分、書きやすくなる)

    $url = 'bbs/file/';
    $url =~ s|/bbs/file/|/chat/data/|;




  • 置換演算子には、置換えを行う際のオプションとして、次の修飾子が用意されています。

    修飾子 意味
    g 繰り返しマッチして置き換える
    i 大文字と小文字の区別をしない
    o 変数展開を1度だけ行う
    m 文字列を複数行として扱う
    s 文字列を単一行として扱う
    x 拡張正規表現を行う
    e 置換文字列を「式」と見なす


    ▽g修飾子の例
    ▽例文(1)
    $word = 'aaaaaa';
    $word =~ s/a/A/;
    print "$word
    \n";

    <出力結果(1)>
    Aaaaaa

    ▽例文(2) : g修飾子を使う場合
    $word = 'aaaaaa';
    $word =~ s/a/A/g;
    print "$word
    \n";

    <出力結果(2)>
    AAAAAA


    ▽e修飾子の例
    $word = "this is 100 yen.";
    $word =~ s/(
    \d+)/$price = $1*2/e;
    print "this is $price yen.
    \n";

    <出力結果>
    this is 200 yen.




7-4. 変換演算子
  • 変換演算子は文字列を1文字づつ順にスキャンして、対象文字列に含まれるすべての文字を変換して、変換した文字数を返す演算子です。
  • 変換演算子は正規表現を使わないので、厳密には正規表現の対象にはならない演算子ではあります。

    構文 意味
    tr/変換対象の文字/変換後の文字/ 「変換対象の文字」をスキャンして「変換後の文字」にすべて変換する
    y/変換対象の文字/変換後の文字/ 上に同じ。


    $word = 'apple';
    $word =~ tr/a-z/A-Z/;
    print "$word
    \n";

    <出力結果>
    APPLE

    $word = 'apple';
    $count = $word =~ tr/a-z/A-Z/;
    print "$count
    \n";

    <出力結果>
    5
    (変換した文字数が5個のため)


  • 変換演算子にも修飾子が次のとおり用意されています。

    修飾子 意味
    c 「変換対象の文字」を反転させる。(「変換対象の文字」に含まれない文字すべてをスキャンする)
    d 「変換対象の文字」に含まれるが、対応するものが「変換後の文字」にない文字を削除する
    s 変換の結果、同じ文字が連続したものを1文字とする


    ▽s修飾子の例
    $word = 'apple';
    $word =~ tr/a-z/A-Z/s;
    print "$word
    \n";

    <出力結果>
    APLE




7-5. 正規表現を利用する関数
  • 正規表現を利用する関数として、split関数 があります。
  • また、split関数の逆変換を行うものとして、join関数 がありますので、併せて使い方を認識しておきましょう。(join関数は正規表現は使用しません)

    split関数 split /パターン/, 文字列, 最大分割数
    split /パターン/, 文字列
    split /パターン/
    split
    「文字列」を「パターン」でマッチするものに「最大分割数」まで分割する。
    「最大分割数」省略時は、末尾の空フィードは切り捨てられる。
    「文字列」省略時は、変数 $_ が充てられる。
    「パターン」省略時は、先頭の空白文字を飛ばした後、空白文字をパターンとする。( /\s+/ )
    join関数 join 区切文字, 配列 区切り文字として間に「区切文字」をはさみ込み、「配列」内の各文字列を連結する。


    $word = "apple:banana:orange";
    @word = split(/:/, $word);

    print "@word
    \n";

    <出力結果>
    apple banana orange

    @word = ("apple", "banana", "orange");
    $word = join ":", @word;

    print "$word
    \n";

    <出力結果>
    apple:banana:orange

阅读(1039) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~