正規表現(4) 検索オプション /m

他にも色々な検索オプションがあります。

正規表現の中で「^」(サーカムフレックス)と「$」(ドル記号)はそれぞれ「文字列の先頭」「文字列の末尾」という意味を持っています。

use strict;
 
$_ = "One Two Three Four Five";
print "$_\n";
 
print (/^One/   ? "o" : "x");  # 先頭の One
print (/One/    ? "o" : "x");  # One
print (/One$/   ? "o" : "x");  # 末尾の One
print " One\n";
 
print (/^Three/ ? "o" : "x");  # 先頭の Three
print (/Three/  ? "o" : "x");  # Three
print (/Three$/ ? "o" : "x");  # 末尾の Three
print " Three\n";
 
print (/^Five/  ? "o" : "x");  # 先頭の Five
print (/Five/   ? "o" : "x");  # Five
print (/Five$/  ? "o" : "x");  # 末尾の Five
print " Five\n";

「A ? B : C」は A が真なら B を、偽なら C を返す「三項演算子」と呼ばれる演算子です。また、検索対象の文字列を指定せずに正規表現を記述すると、$_ が検索対象となるのでした。
つまり (/検索パターン/ ? "o" : "x") は検索パターンが $_ の一部にマッチすれば "o" が、マッチしなければ "x" が返ってきます。
実行結果です。

One Two Three Four Five
oox One
xox Three
xoo Five

「/m」オプションを使うと、この「^」と「$」がそれぞれ「行頭」「行末」(改行文字 \n の後ろと前)にもマッチするようになります。これにより、複数行の文字列からの検索がとっても簡単になります。

m/^apple/m;   # 行頭にある apple にマッチ。
m/lemon$/m;   # 行末にある lemon にマッチ。
m/^grape/im;  # 行頭にある grape にマッチ。大文字小文字を区別しない。
              # このように複数のオプションも指定可能。
              # オプションの順番は特に関係ない。 

早速使ってみます。

use strict;
 
my $text = "I LOVE A FRESH APPLE SO MUCH!
An apple pie and banana juice as well.
They are so lovely.";
print "$text\n\n";
 
my @patterns = (
    'banana juice', '^banana juice',
    'An apple',     '^An apple',
    'lovely\.',     'lovely\.$',
);
 
for my $pattern (@patterns) {
    printf "%-15s", $pattern;
    print ($text =~ /$pattern/im ? "o\n" : "x\n");
}

@patterns に入れた正規表現を $text に対して順番に適用しています。
printf は書式付きで出力できる関数です(C言語のものと同じです)。「printf "%-15s", $pattern;」は、$pattern を文字列として左詰め・幅15で出力します。文字列の幅が足りない場合は空白で埋められます。書式について詳しくは「perldoc -f sprintf」などをご覧ください。
実行結果です。

I LOVE A FRESH APPLE SO MUCH!
An apple pie and banana juice as well.
They are so lovely.

banana juice   o
^banana juice  x
An apple       o
^An apple      o
lovely\.       o
lovely\.$      o

「^An apple」は通常、文字列の先頭の An apple にしかマッチしませんが、「/m」オプションを付けた事で、2行目の行頭にある An apple にマッチしています。

複数行の文字列は扱う機会が多いはずですので、「/m」オプションは知っておくと便利ですね。(^_^)

正規表現(3) 検索オプション /o

昨日に引き続き、Perlでの正規表現を勉強します。検索パターンは「m//」演算子で記述できるのでした。

m/Apple|Banana/

このパターンの場合、「Apple」「Banana」にはマッチしますが、「apple」や「BANANA」にはマッチしません。パターンは大文字小文字を厳格に区別するのです。
例えば

m/Apple|APPLE|apple|Banana|BANANA|banana/

や、[ ] で文字クラス*1を使って

m/[Aa][Pp][Pp][Ll][Ee]|[Bb][Aa][Nn][Aa][Nn][Aa]/

のように書けばマッチするようになりますが……面倒ですね。(^_^;)

そこで、検索オプション(/o 修飾子 : スラッシュ・オー・しゅうしょくし)の出番です。検索パターンの最後の「/」(スラッシュ*2)の、さらに後ろに「正規表現パターンの挙動を制御する為の検索オプション」を指定する事ができます。
「/i」オプションを用いると、「大文字小文字を区別しなくなる」ようになります。先ほどのパターンにこのオプションを付ける場合、以下のように書きます。

m/Apple|Banana/i

コードを書いて試してみましょう。

use strict;
 
my $text = "I LOVE A FRESH APPLE SO MUCH!
An apple pie and banana juice as well.
They are so lovely.";
print "$text\n\n";
 
print "m/Apple|Banana/  ... ";
if ($text =~ m/Apple|Banana/) {
    print "Matched\n";
} else {
    print "Not matched\n";
}
 
print "m/Apple|Banana/i ... ";
if ($text =~ m/Apple|Banana/i) {
    print "Matched\n";
} else {
    print "Not matched\n";
}

$text の文章には「APPLE」「apple」「banana」はあっても「Apple」「Banana」はありません。この文章に「m/Apple|Banana/」という検索パターンを、/i オプションを付けた場合と付けない場合でマッチするか試しています。
以下が実行結果です。

I LOVE A FRESH APPLE SO MUCH!
An apple pie and banana juice as well.
They are so lovely.

m/Apple|Banana/  ... Not matched
m/Apple|Banana/i ... Matched

/i オプションを付けるとマッチしていますね。

最後に「i」と付けただけなのに、「apple」にも「BANANA」にも「ApPlE」にも「bANANa」にもマッチするようになります。とても便利です。(^_^)

*1:[abc]で"a"か"b"か"c"のどれか1文字にマッチします。[a-z]で英小文字1文字、[^abc]で"a" "b" "c"以外の何か1文字にマッチします。

*2:頭に m と付けた場合はスラッシュ以外の文字をパターン区切りとして使えるのでしたね。その場合は最後の区切りの後になります。