括弧()の位置による取得文字列の違い

正規表現パターンの中に括弧を記述することで、パターンの一部が文字列のどの部分にマッチしたのかを取得できますが、括弧を記述する位置によってどの部分にマッチするかが変わってきます。ここでは Perl の正規表現でパターンの中に括弧を記述した場合の括弧を記述する位置よる違いについて解説します。

(Last modified: )

メタ文字「+」と組み合わせる場合

最初にメタ文字の + が含まれるパターンで括弧を記述する場合です。次のパターンを見てください。

/(\d+)yen/

\d+ は数字が 1 回以上繰り返された場合にマッチします。そして \d+ 全体が括弧 () で括られていますので、このパターンがマッチした場合、変数 $1 には \d+ にマッチした全体が格納されます。

下記の場合ですと、変数 $1 には "2391" が格納されます。

my $str = "book is 2391yen, cake is 800yen";

if ($str =~ /(\d+)yen/){
  print "$1\n";
}

今度は次のようにパターンを記述してみます。

/(\d)+yen/

(\d)+ 全体としては数字が 1 回以上繰り返された場合にマッチすることに代わりはありませんが、括弧は \d だけを括っています。この場合は \d にマッチした文字が都度変数 $1 に格納されます。メタ文字 + によって \d とマッチするかどうかが 1 回以上繰り返され、最後に \d にマッチした文字が変数 $1 に最後に格納されます。

下記の場合ですと、変数 $1 には "2" , "3" , "9" , "1" と順番に上書きで格納されていくので、変数には "1" が格納されます。

my $str = "book is 2391yen, cake is 800yen";

if ($str =~ /(\d)+yen/){
  print "$1\n";
}

メタ文字「?」や「*」と組み合わせる場合

メタ文字の ?* が含まれるパターンで括弧を記述する場合です。

まず繰り返しを表すメタ文字が括弧の中にある場合です。

/(\d*)yen/

この場合、変数 $1 には括弧で括られた \d* にマッチした文字列が格納されます。 1 回以上マッチした場合はメタ文字 + の場合と同じですが、 0 回マッチした場合には \d* は空文字にマッチしたことになるため変数 $1 には空文字が格納されます。

次に繰り返しを表すメタ文字が括弧の外にある場合です。

/(\d)*yen/

この場合、変数 $1 には \d にマッチした文字格納されますが、 \d に一度もマッチしまなかった場合は変数 $1 には値が一度も格納されず未定義値(undef)となります。ただし (\d) に対してメタ文字 * が設定されていますのでパターン全体としてマッチするかどうかに影響ありません。

このようにメタ文字の *? を使用する場合に一度もマッチしない場合の挙動が若干異なります。

サンプルコード

それでは簡単なサンプルを作成します。

use strict;
use warnings;
use utf8;
binmode STDIN, ':encoding(cp932)';
binmode STDOUT, ':encoding(cp932)';
binmode STDERR, ':encoding(cp932)';

&check1("book is 1234yen, cake is 800yen");
&check2("book is 1234yen, cake is 800yen");

sub check1{
  if ($_[0] =~ /(\d+)yen/){
    print $_[0]." は /(\\d+)yen/ にマッチします。\n";
    print "\$1: $1\n";
  }
}

sub check2{
  if ($_[0] =~ /(\d)+yen/){
    print $_[0]." は /(\\d)+yen/ にマッチします。\n";
    print "\$1: $1\n";
  }
}

テキストエディタでプログラムを記述したあと sample.pl という名前で保存します。(文字コードは UTF-8 です)。コマンドプロンプトを起動し、プログラムを保存したディレクトリへ移動したあとで次のように実行します。

perl sample.pl

次のように実行結果が表示されます。

括弧()の位置による取得文字列の違い(1)

括弧の位置が違う 2 つのパターンを作成し、それぞれ同じ文字列を対象にマッチするかどうか調べたあと、どの部分にマッチしたのかを取得して画面に表示しました。

-- --

Perl の正規表現でパターンの中に括弧を記述した場合の括弧を記述する位置よる違いについて解説しました。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。