文字の置換

■ 文字列の一部分を置換する(s/.../.../)

◆ 文字列の置換

s/.../.../ は、$str =~ s/reg/str/ のように使用し、$str の中から正規表現 reg にマッチする部分を文字列 str に置換します。例えば下記の例では Mike を John に置換します。

replace1.pl
$str = "My name is Mike Smith.";
$str =~ s/Mike/John/;
print "$str\n";

結果は次のようになります。

My name is John Smith.

■ 大文字小文字を区別しないで置換する(s/.../.../i)

◆ 大文字・小文字を区別しない

s/.../.../i は、マッチングを行う際に、大文字・小文字を区別しないで比較します。

replace2.pl
$str = "Tanaka";
$str =~ s/TANAKA/SUZUKI/i;
print "$str\n";

TANAKA は Tanaka にもマッチして、これを SUZUKI に置換します。結果は次のようになります。

SUZUKI

s/.../.../igo などのように、他のオプションと組み合わせて指定することもできます。

■ マッチする部分をすべて置換する(s/.../.../g)

◆ 全置換

通常に s/.../.../ を用いると、最初にマッチした部分のみを置換しますが、s/.../.../g は、マッチする部分すべてを置換します。

replace3.pl
$str = "aaa";
$str =~ s/a/A/;          # 最初の a のみを置換
print "$str\n";

$str = "aaa";
$str =~ s/a/A/g;         # すべての a を置換
print "$str\n";

結果は次のようになります。

Aaa
AAA

■ 置換文字を式で与える(s/.../.../e)

◆ 置換文字に Perl のスクリプトを使用する

s/.../.../e の形式では、置換文字の部分に Perl 構文を利用することができます。例では、\d+ が1文字以上の数値にマッチします。これを $1 として参照しながら、sprintf() で0埋め2桁の数値に変換し、その結果に置換します。eg の g はマッチした文字をすべて置換することを意味します。

replace4.pl
$str = "99/1/1";
$str =~ s/(\d+)/sprintf("%02d", $1)/eg;
print "$str\n";

実行結果は次のようになります。

99/01/01

■ 高速に置換する(s/.../.../o)

◆ 高速置換

s/.../.../o の形式を用いると、マッチングを高速化することができます。

while (<>) {
    s/^From:/発信者/o;
    print;
}

正規表現のコンパイル作業をスクリプトの起動時に1回だけ行うため、正規表現の中で変数を用いて動的に変更しても、変数の変化を反映することができません。

■ 正規表現の中でスラッシュを沢山使う(s|...|...|)

◆ 斜めつまようじ症候群の回避

これも「斜めつまようじ症候群」を回避するテクニックです。s/.../.../ では通常スラッシュを用いますが、s|...|...| や s!...!...! などのように、スラッシュ以外の記号文字も使用することができます。下記はどちらも、/usr/local/bin/ を /usr/bin/ に置換するスクリプトですが、後者の方が読みやすくなります。

# 斜めつまようじ症候群に陥っている例
$str = "/usr/local/bin/perl";
$str =~ s/\/usr\/local\/bin\//\/usr\/bin\//;
print "$str\n";

# すっきりした例
$str = "/usr/local/bin/perl";
$str =~ s|/usr/local/bin/|/usr/bin/|;
print "$str\n";

■ HTMLのコメントを削除する(*?)

◆ 最短マッチング

<!-- と --> で囲まれるコメント部を削除します。単に <!--.*--> とすると最長マッチングとなり、一番最初の <!-- と一番最後の --> の間がすべて削除されてしまいますが、Perl 5 でサポートされた最短マッチング *? により、都合よくコメント部を削除することができるようになります。

delcomment.pl
$xx = "111 <!-- 222 --> 333 <!-- 444 --> 555";
$xx =~ s/<!--.*-->//g;            # うまく削除できない例
print "$xx\n";

$xx = "111 <!-- 222 --> 333 <!-- 444 --> 555";
$xx =~ s/<!--.*?-->//g;           # うまく削除できる例
print "$xx\n";

実行結果は次のようになります。

111  555
111  333  555

■ 特定文字を対応する文字に置換する(tr/.../.../, y/.../.../)

◆ 文字単位の置換

tr/.../.../ は、文字単位の置換を行います。下記の例では、a を A に、b を B に、c を C に置換します。y/.../.../ も tr/.../.../ と同じ意味を持ちます。

$str1 = "cab";
$str1 =~ tr/abc/ABC/;
print "str1 = $str1\n";                  # CAB と表示される
◆ 範囲指定

ハイフン(-)を用いて文字の範囲を指定することもできます。下記の例では、a~z を、対応する A~Z に置換します。

$str2 = "cab";
$str2 =~ tr/a-z/A-Z/;
print "str2 = $str2\n";                  # CAB と表示される
◆ 連続文字の指定

下記のように s オプションを指定すると、連続する aaaaaa... が、1文字の a に置換されます。

$str3 = "Baaaaaan!";
$str3 =~ tr/a/a/s;
print "str3 = $str3\n";                  # Ban! と表示される
◆ 含まれる文字数を数える

対応する文字が無い場合は置換は行われません。また、tr/.../.../ は置換した文字数を返します。このことを利用して、文字列の中に指定した文字が何文字あるか数えることができます。下記の例では、BANANA の中に A が何個含まれているか数えます。

$str4 = "BANANA";
$count = ($str4 =~ tr/A//);
print "count = $count\n";                # 3 と表示される

Copyright (C) 2002 杜甫々