Perlのすべてがここにある!

Perl:正規表現を用いた文字列の検索・置換

やまぐち

やまぐち

開発エンジニア/Perl/PHP/リーダー/ボールド歴4年

正規表現とは、文字列の一部をパターン化して表現する方法です。文章の中からある文字列を検索する時、検索したい文字列をそのまま指定するのではなく、文字列の一部をパターン化して検索する(パターンに基づいた仮の文字列を作成して検索する)場合などに正規表現を使います。

例えばWindowsLinuxでも、ファイルや文字列を検索するときに使用される正規表現として「*」(ワイルドカード)が知られていると思います。パターンを『app*』と表現すると、「apple」「application」などが含まれるファイル、文字列がマッチします。

Perlの場合、他の言語に比べて非常に有用な正規表現によるパターンマッチ機能が実装されており、より簡単に、かつ詳細にパターンマッチを実行することができます。


1.基本的な使い方

Perlでは正規表現を「パターン」と呼ぶことが多いです。文字列に対してパターンがマッチすれば(成功すれば)真を返し、マッチしなければ(失敗すれば)偽を返します。

パターンはスラッシュで囲んで指定します。この場合のスラッシュのように正規表現を囲む記号を「デリミタ」と呼びます。

$_ = 'abcdefg';

if (/cde/) {
  print 'マッチしました';
}
else {
  print 'マッチしませんでした';
}

例では、条件判定のところにパターンだけ記述されていて文字列が何も指定されていません。この場合はデフォルト変数「$_」に対してcdeが含まれているかのマッチングを行います。その他の変数に対してマッチングを行うには、結合演算子『=~』を使用します。

my $word = 'abcdefg';

if ($word =~ /cde/) {
  print 'マッチしました';
}
else {
  print 'マッチしませんでした';
}

Perlでは、正規表現を使用する場合に特別な関数をタイプする必要はありません。また、パターンマッチを行う際は「!~」を使うこともできます。「!~」はパターンがマッチすれば(成功すれば)偽を返し、マッチしなければ(失敗すれば)真を返します。

my $word = 'abcdefg';

if ($word !~ /cde/) {
  print 'マッチしませんでした';
}
else {
  print 'マッチしました';
}

2.文字列を検索 ~ パターンマッチ演算子「m//

スラッシュでパターンを囲むのは、実際はパターンマッチ演算子「m//」のショートカットを意味します。「m」を明示することによって任意のデリミタを使用できるようになります。デフォルトのスラッシュを使う場合には「m」を書く必要はありません。

任意のデリミタは、よく使われる「m{pattern}(ブレース)」のように対になった記号や、「m%pattern%」のように1種類の記号で始まりと終わりを囲む方法が使えます。当然ですが、パターンの中で使用しない記号を選ばなければなりません。例えばURLのような書式は、デリミタがスラッシュのままではエスケープが多くなり、見難くなってしまうので、あまりURLに登場しない記号をデリミタに使います。

my $url = 'http://example.com/';

print ($url =~ m{^https://} ? 'HTTPSです' : 'HTTPSではありません');

3.文字列を置換 ~ 置換演算子「s///

文字列の置換には「s///」を使用します。「s/パターン/置換文字列/」のような形式で表記し、パターンにマッチした文字列を全て置換文字列に置き換えます。マッチに失敗した場合は変数の値は変わりません。

my $url = 'http://example.com/';
$url =~ s%^http://%https://%;
print $url;

> https://example.com/

また「m//」と同じく任意のデリミタを指定することができます。デフォルトのスラッシュを使う場合でも「s」は必要です。ブレースのように対になったデリミタは、パターンを一度閉じるようにデリミタを4つ使って表記します。最初のパターンのデリミタと置き換え文字列のデリミタを違うカッコにすることも可能です。

my $url = 'http://example.com/';
$url =~ s{^http://}(https://);
print $url;

4.特殊文字 ~ メタキャラクタ

実際のソースコード上は、基本的な使い方の例にあげた「cde」のような固定文字列にマッチさせることはあまりありません。そのために正規表現では特殊な意味を持つメタキャラクタが用意されています。

サンプル

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

4-1.文字クラス

メタ文字意味
.(ドット)ワイルドカード。改行を除くあらゆる1文字にマッチ。
[…](角括弧)文字クラス。カッコ内の文字のどれか1つにマッチ。
\d数字。[0-9]と同じ。
\D数字以外。[^0-9]と同じ。
\w単語構成文字。[a-zA-Z0-9_]と同じ。
\W単語構成文字以外。[^a-zA-Z0-9_]と同じ。
\s空白文字。[ \t\n\r\f]と同じ。
\S空白文字以外。[^\t\n\r\f]と同じ。
my $word = 'Apple, Orange, Grape, Banana, Peach';

if ( $word =~ /A.O/ ) {
  print "'A'と'O'の間に1文字見つかりました。\n";
}
if ( $word =~ /[AB]/ ) {
  print "'A'と'B'が見つかりました。\n";
}

文字クラスの中では、(ハイフン)を使って文字の範囲を指定することができます。[a-z]とすれば小文字アルファベットaからzまでのどれかにマッチします。[a-zA-Z]は大文字小文字のアルファベット、[b-e]bからeまでのアルファベットどれかにマッチします。[0-9]0から9の数字にマッチします。

my $word = 'abcdefg';

if ( $word =~ /[a-z]/ ) {
  print "小文字のアルファベットが含まれています。";
}

場合によっては含まれない文字を探した方が早い場合もあります。文字クラスの先頭に^(キャレット)を置くと、指定した文字以外の文字にマッチするようになります。

my $word = 'abcdefg';

if ( $word =~ /[^a-zA-Z0-9]/ ) {
  print "半角英数字以外の文字が含まれています。";
}

^(キャレット)は、下で示す位置指定でも使用されるメタキャラクタです。混同しないように注意しましょう。

4-2.グループと選択

メタ文字意味
(…)(丸括弧)文字列のグループ化。カッコ内の文字列をひとつの文字として扱う。
|(垂直バー)選択肢。どちらか一方にマッチ。
my $word = 'Apple, Orange, Grape, Banana, Peach';

if ( $word =~ /(Apple|Grape)/ ) {
  print "'Apple'か'Grape'が含まれています。\n";
}

4-3.位置指定

メタ文字意味
^(キャレット)文字列の先頭または行頭にマッチ。
$(ドル記号)文字列の末尾または行末にマッチ。
my $word = 'Apple, Orange, Grape, Banana, Peach';

if ( $word =~ /^Apple/ ) {
  print "' Apple'から始まっています。\n";
}
if ( $word =~ /Peach$/ ) {
  print "'Peach'で終わっています。\n";
}

4-4.繰返し指定

メタ文字意味
*(アスタリスク)0個以上でマッチ。文字が無くてもマッチ。
+(プラス)1個以上でマッチ。
?(クエスチョン)0個または1個にマッチ。
{COUNT}(繰り返す数)きっかりCOUNTの回数繰り返す。
{MIN,}(最低回数,)MINの回数以上繰り返す。
{MIN,MAX}(最低回数,最高回数)MINの回数以上MAXの回数以下繰り返す。
my $word = 'abcdeeeeefghjiklmnopppppqrstuvwxyz';
                ^^^^^          ^^^^^
if ( $word =~ /e+/ ) {
  # $&には直前にマッチした文字列が入ります。
  print "$&\n";
}

> eeeee

繰返し指定は可能な限り多くの文字をマッチさせます。これを「最長マッチ」と言います。一方、出来る限り少ない文字でマッチさせることを「最短マッチ」と言います。最小マッチさせるには、最長マッチの繰返し指定の後に「?」を追加します。

メタ文字意味
*?0個以上でマッチ。文字が無くてもマッチ(最短マッチ)。
+?1個以上でマッチ(最短マッチ)。
??0個または1個にマッチ(最短マッチ)。
{MIN,}?MINの回数以上繰り返す(最短マッチ)。
{MIN,MAX}?MINの回数以上MAXの回数以下繰り返す(最短マッチ)。
my $word = 'abcdeeeeefghjiklmnopppppqrstuvwxyz';
                ^^^^^          ^^^^^
if ( $word =~ /e+?/ ) {
  print "$&\n";
}

> e

5.オプション修飾子 ~ フラグ

正規表現の動作を変更できる「オプション修飾子」があります。単に「オプション」とか「フラグ」と呼ばれることもあります。オプションは最後のデリミタの直後に指定します。複数オプションはまとめて指定することもできます。

オプション意味
/i大文字と小文字を区別せずにマッチする。
/m^や$が行頭や行末にマッチするようにする。
/sワイルドカードの.(ドット)を改行にもマッチさせる。
/xパターンにある空白文字を無視してコメントを書けるようにする。
/oパターンのコンパイルを一回だけ行う。
/gグローバルマッチ。すべてのマッチを見つける。置換時はs///はすべて置き換える。
/e置換時のみ。置き換え文字列を式として評価する。
my $word = 'This book is 500 yen.';

$word =~ s/(\d+)/$1*2/e;
print "$word\n";

> This book is 1000 yen.

6.最後に

正規表現が本領を発揮するのは、マッチした部分を切り出して再利用する場合や、置換・削除する時です。これらの例を参考に、皆さんも多くの正規表現を使ってみてはいかがでしょうか。

私たちは、全てのエンジニアに市場価値を高め自身の望む理想のキャリアを歩んでいただきたいと考えています。もし、今あなたが転職を検討しているのであればこちらの記事をご一読ください。理想のキャリアを実現するためのヒントが見つかるはずです。

『技術力』と『人間力』を高め市場価値の高いエンジニアを目指しませんか?

私たちは「技術力」だけでなく「人間力」の向上をもって遙かに高い水準の成果を出し、関わる全ての人々に感動を与え続ける集団でありたいと考えています。

高い水準で仕事を進めていただくためにも、弊社では次のような環境を用意しています。

  • 定年までIT業界で働くためのスキル(技術力、人間力)が身につく支援
  • 「給与が上がらない」を解消する6ヶ月に1度の明確な人事評価制度
  • 平均残業時間17時間!毎週の稼動確認を徹底しているから実現できる働きやすい環境

現在、株式会社ボールドでは「キャリア採用」のエントリーを受付中です。

まずは以下のボタンより弊社の紹介をご覧いただき、あなたの望むキャリアビジョンをエントリーフォームより詳しくお聞かせください。

コメント

公式アカウントLINE限定!ボールドの内定確率が分かる無料診断実施中
公式アカウントLINE限定!
ボールドの内定確率が分かる無料診断実施中