|
|
Perl正規表現の使い方 パターンへの変数展開 |
H.Kamifuji . |
ここまでは対象の文字列が正規表現にマッチするかどうかを判別していましたが、ここではマッチした場合に、実際にマッチした部分文字列を取得する方法を確認します。 当ページでは、Linux CentOS7 の Gnome で動作テストしています。 |
|
パターンはダブルクオーテーションで囲った文字列と同じように扱われます。その為、ダブルクオーテーションで囲われた文字列の中に変数を記述した場合と同じくパターン内に変数を記述した場合は変数展開が行われます。(文字列中の変数展開については「文字列中の変数展開」を参照して下さい)。 具体的な例で考えてみます。 my $pattern = "and"; my $str = "copy and paste"; if ($str =~ /$pattern/){ print "$str\n"; }上記ではパターンとして変数名が記述されています。この場合、変数「$pattern」に格納された値が変数展開され次のように記述した場合と同じになります。 my $str = "copy and paste"; if ($str =~ /and/){ print "$str\n"; }このように変数を指定することで、パターンを動的に指定することが出来ます。 先ほどは変数名だけをパターン内で指定しましたが、他のパターンと組み合わせることも可能です。 my $pattern = "and"; my $str = "copy and paste"; if ($str =~ /\w$pattern/){ print "$str\n"; }また変数名と他のパターン内の文字の区切りが明確で無い場合は、文字列の中に変数を記述する場合と同じく「$」以降の変数名を{}で括って下さい。 my $pattern = "and "; my $str = "copy and paste"; if ($str =~ /${pattern}paste/){ print "$str\n"; }では簡単なプログラムで確認して見ます。 test1-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 変数の展開 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; &check1("and", "copy and paste"); &check2("(J|j)ava", "disable JavaScript"); &check2("(J|j)ava", "disable javaScript"); &check2("(J|j)ava", "disable javascript"); sub check1{ my ($pattern, $str) = @_; if ($str =~ /$pattern/){ print "対象文字列: $str\nマッチ部分: $&\n\n"; } } sub check2{ my ($pattern, $str) = @_; if ($str =~ /${pattern}Script/){ print "対象文字列: $str\nマッチ部分: $&\n\n"; } }上記を「test1-1.pl」の名前で保存してから次のように実行して下さい。 ![]() Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test1-1_u.pl | nkf -w 対象文字列: copy and paste マッチ部分: and 対象文字列: disable JavaScript マッチ部分: JavaScript 対象文字列: disable javaScript マッチ部分: javaScript [xxxxxxxx@dddddddddd Var]$ |
変数と同じく配列をパターン内に記述すると変数展開が行われます。配列の変数展開の仕方はダブルクオーテーションで囲われた文字列の中に配列を記述した場合と同じです。(配列の文字列中の変数展開については「文字列中に含まれる配列の変数展開」を参照して下さい)。 具体的な例で考えてみます。 my @pattern = ("color", "red"); my $str = "background color red"; if ($str =~ /@pattern/){ print "$str\n"; }上記ではパターンとして配列名が記述されています。この場合、配列「@pattern」に格納された値が変数展開され次のように記述した場合と同じになります。 my $str = "background color red"; if ($str =~ /color red/){ print "$str\n"; }基本的には変数を記述した場合と同じです。(デフォルトでは配列の各要素がスペースで区切られて展開されますが、特別な変数「$"」に対して区切り文字を設定することが可能です)。 変数の場合と同じく配列名と他のパターンを組み合わせることも可能です。 my $pattern = "and"; my $str = "copy and paste"; if ($str =~ /\w@pattern/){ print "$str\n"; }また配列名と他のパターン内の文字の区切りが明確で無い場合は、文字列の中に配列を記述する場合と同じく「@」以降の配列名を{}で括って下さい。 my @pattern = ("color", "red "); my $str = "background color red and foreground color black"; if ($str =~ /@{pattern}and/){ print "$str\n"; }では簡単なプログラムで確認して見ます。 test2-1.pl サンプルプログラム下記のサンプルを実行してみよう。# 配列の展開 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; $" = "|"; &check("background red"); &check("foreground yellow"); &check("border white"); sub check{ my ($str) = @_; my @color = ("black", "red", "white"); if ($str =~ /(@color)/){ print "対象文字列: $str\nマッチ部分: $&\n\n"; } }上記を「test2-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 今回のサンプルでは配列の変数展開時の区切り文字として変数「$"」に対して「|」を設定しています。よってパターンは「/(black|red|white)/」となっています。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test2-1_u.pl | nkf -w 対象文字列: background red マッチ部分: red 対象文字列: border white マッチ部分: white [xxxxxxxx@dddddddddd Var]$ |
パターン内で記述された変数や配列は、ダブルクオーテーションで囲われた文字列の中に記述された場合と同じく変数展開が行われますが、パターンの記述を行う時、m//演算子の区切りに''を使った場合は変数展開は行われません。 m'パターン'具体的な例で考えてみます。 my @pattern = ("color", "red"); my $str = "background color red"; if ($str =~ /@pattern/){ print "$str\n"; }上記のようにパターンの記述を「/@pattern/」のように行った場合は、パターン内に配列の変数展開が行われます。 my @pattern = ("color", "red"); my $str = "background color red"; if ($str =~ m'@pattern'){ print "$str\n"; }上記の場合は配列の変数展開が行われずに「@pattern」と言う文字列が記述されたパターンとして解釈されます。 では簡単なプログラムで確認して見ます。 サンプルプログラム下記のサンプルを実行してみよう。# m//演算子の区切りに''を使った場合 use strict; use warnings; use utf8; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)'; $" = "|"; &check1('hogehoge@color'); &check2('hogehoge@color'); &check1("border white"); &check2("border white"); sub check1{ my ($str) = @_; if ($str =~ m'(@color)'){ print "パターン: m'(\@color)'\n"; print "対象文字列: $str\nマッチ部分: $&\n\n"; } } sub check2{ my ($str) = @_; my @color = ("black", "red", "white"); if ($str =~ m/(@color)/){ print "パターン: m/(\@color)/\n"; print "配列\@color: @color\n"; print "対象文字列: $str\nマッチ部分: $&\n\n"; } }上記を「test3-1.pl」の名前で保存してから次のように実行して下さい。 ![]() 今回はパターンの記述方法として「m''」と「m//」を使用しています。使用している区切り文字の違いによって同じパターンであってもマッチする文字列は異なります。 Linux 環境での実行結果は、下記です。シフトJIS で出力されるので nkf -w で UTF-8 に変換しています。 [xxxxxxxx@dddddddddd Var]$ perl test3-1_u.pl | nkf -w パターン: m'(@color)' 対象文字列: hogehoge@color マッチ部分: @color パターン: m/(@color)/ 配列@color: black|red|white 対象文字列: border white マッチ部分: white [xxxxxxxx@dddddddddd Var]$ |
|