Perl正規表現の基本 3/3

置換演算子 s/パターン/文字列/

置換演算子(substitution operator)を使うと、正規表現にマッチした部分を他の文字列に置換することができます。

s/正規表現(パターン)/ダブルクォート風の文字列/

置換演算子s///は、ブール値を返却します。・・・と「初めてのPerl」には紹介されていますが(それはそれで間違いではないのですが)、厳密には「マッチした回数」を返却します。s///の場合は、マッチした場合は1、しなかった場合は0となり、/gオプションをつけると、2, 3, 4, ・・・のように複数回マッチの値も返却されます。

/gをつけるとグローバル置換(該当する全てを置換)になります。この場合、置換はオーバーラップしません。つまり、一度置き換えられた結果が再度正規表現にマッチしたとしても、それ以上置換はされません。

また、前回出てきた/iや/sといったオプション修飾子も使用することができます。

$_ = "I am studying Perl.\n";
s/I am/You are/;
print;

$_ = "putty, poderosa, winscp\n";
s/p/P/g;
print;

実行結果
You are studying Perl.
Putty, Poderosa, winscP

スラッシュ以外のデリミタを使う場合の注意点

デリミタにはスラッシュ以外を使用することができますが、左右で一対になるデリミタの場合、以下のように二つの組が別のデリミタでもOKです。

s<perl>#Perl#;
s[perl]{Perl};

結合演算子 =~ を使ってデフォルト変数以外の変数を置換する

前回、m//演算子での=~について「マッチした値を左辺に代入するのではない」と書きましたが、s///演算子で=~を使う場合は異なります。

まず、m//とs///の違いを明確に理解する必要があります。

m//  : 正規表現にマッチするかどうかを判定し、ブール値を返却する
s/// : 正規表現にマッチした場合、対象文字列のマッチする箇所を置換上書きし、ブール値を返却する

結合演算子=~は、これらの処理の対象として左辺値をとるものです。

つまり、s///で結合演算子=~を使用した場合、対象となる左辺にある文字列(もしくは変数が指す文字列)が置換されます。

しかし、あくまで結合演算子=~は左辺を対象として右辺の処理を行っているという点に注意が必要です。

my $str = "I like Perl.";
$str =~ s/like/love/;
print $str, "\n";

実行結果
I love Perl.

アルファベットの大文字小文字置換

アルファベットの大文字・小文字への置換は逆スラッシュエスケープを使用します。s///の右辺(置換後)において、逆スラッシュ以降に続くものを強制的に変換します。

\U : 以降全てを大文字へ
\L : 以降全てを小文字へ
\E : 変換の終了ポイント

\u : 続く一文字だけを大文字へ
\l : 続く一文字だけを小文字へ

これを応用するとワードの頭だけ大文字で以降は小文字というよくあるパターンは以下のようになります。

$target =~ s/(\w+)/\u\L$1/g;

以上が置換の基本的な使用方法となります。

正規表現をsplit関数のセパレータとして使用する

Perl正規表現には、今まで見てきたパターンマッチ・置換処理の他に、文字列分割時のセパレータとしての利用方法があります。

splitは正規表現によるセパレータ(区切り)の間に挟まれた文字列のリストを返却します。

my @array = split /\t/, $target;

splitを使用する際の注意点としては、「先頭の空フィールドは必ず返されるが、末尾の空フィールドは破棄される」という点です。フィールドとはセパレータで区切られた部分文字列のことです。

my @array = split /:/, "::1:2:3::::";
print $_,"," for(@array);

実行結果
,,1,2,3,

splitによって分割された文字列、または文字列の配列をひとつの文字列に結合したい場合は、join関数を使用します。

join関数は第一引数に「のり」のように挟み込む文字列(≠パターン)を指定し、第二引数以降に結合したい部分文字列を指定します。

my $joined_ex1 = join ":", "hoge", "foo", "var";
print $joined_ex1, "\n";

my @array = ( "hoge", "foo", "var");
my $joined_ex2 = join ":", @array;
print $joined_ex2, "\n";

実行結果
hoge:foo:var
hoge:foo:var