正規表現演算子 s///

文字列の中のパターンを置換する

構文

解説

[Perlop の翻訳です]

s/// は、パターンに一致する文字列を検索し、もし見つかれば、 そのパターンを置換テキストで置き換え、行われた置換の数を返します。 見つからなければ、false を返します ("Relational Operators" の記載のとおり、 空文字列("")でもあり数値のゼロ(0)でもある値)。

もし /r (非破壊的) オプションが使われると、それは文字列のコピーで置換を実行し、 置換の数を返す代わりに、置換が発生したか否かに関わらず、そのコピーを返します。 オリジナルの文字列は、/r が使われたときには、決して変更されません。 コピーは、たとえ入力がオブジェクトだろうが tie された変数であろうが、必ずプレーンの文字列になります。

もし =~!~ 演算子を通して何も文字列が指定されなければ、 $_ 変数が検索され変更されます。 /r オプションが使われない限り、指定の文字列は、スカラー変数、配列要素、ハッシュ要素、 または、それらいずれかへの代入でなければいけません。 つまり、何かしらのスカラーの左辺値でなければいけません。

もし区切り文字にシングルクォーテーションが選ばれた場合、PATTERNREPLACEMENT のどちらでも変数展開は行われません。 区切り文字がシングルクォーテーションでない場合、もし PATTERN に文字列終端テストではなく変数のように見える $ が含まれていたら、その変数は実行時にパターンの中に展開されます。 変数が最初に展開されるときだけパターンにコンパイルしてほしいなら、/o オプションを使ってください。 パターン評価の結果が空文字列なら、最後に実行して成功した正規表現が代わりに使われます。 これらに関して詳しい説明は perlre をご覧ください。

オプションは m// と同じものに加えて、次の置換に特化したオプションが利用できます。

オプション 説明
e 右側を式として評価します。
ee 右側を文字列として評価し、その結果を eval します。
r 置換を返し、元の文字列には触らずそのままにします。

区切り文字のスラッシュは、ホワイトスペースでなければどんな文字にでも置き換えることができます。 識別子(変数名や関数名のこと)に使える文字を使う場合は、s の後にスペースを加えてください。 シングルクォーテーションを使うと、置換文字では何ら解釈が行われません(ただし /e はこれに優先します)。 Perl はバックティックを通常の区切り文字として扱う点に注意してください。 置換テキストはコマンドとして評価されません。 もし PATTERN が丸括弧で囲んで区切られているなら、 REPLACEMENT 自身も何かで囲まれます。 つまり、丸括弧で囲まれているかもしれませんし、そうでない文字で囲まれているかもしれません。 例えば、s(foo)(bar)s<foo>/bar/ です。 /e を使うと、置換部分は、その瞬間その場で、一人前の Perl の式として扱われ評価されます。 ただし、それはコンパイル時にチェックされる構文となります。 二つ目の e 修飾子を使うと、置換部分は Perl 式として実行される前に eval されます。

以下、例です。

    s/\bgreen\b/mauve/g;              # ウィンターグリーンを変えないで

    $path =~ s|/usr/bin|/usr/local/bin|;

    s/Login: $foo/Login: $bar/; # 実行時のパターン

    ($foo = $bar) =~ s/this/that/;      # まずコピーしてから
                                        # 変更します
    ($foo = "$bar") =~ s/this/that/;    # 文字列に変換し、
                                        # コピーしてから、変更します
    $foo = $bar =~ s/this/that/r;       # /r を使って上記と同じ
    $foo = $bar =~ s/this/that/r
                =~ s/that/the other/r;  # /r を使って、
                                        # 置換を連結する
    @foo = map { s/this/that/r } @bar   # /r は map で
                                        # とても役に立ちます

    $count = ($paragraph =~ s/Mister\b/Mr./g);  # 変更箇所数を取得する

    $_ = 'abc123xyz';
    s/\d+/$&*2/e;                # 'abc246xyz' になる
    s/\d+/sprintf("%5d",$&)/e;   # 'abc  246xyz' になる
    s/\w/$& x 2/eg;              # 'aabbcc  224466xxyyzz' になる

    s/%(.)/$percent{$1}/g;       # パーセントエスケープを変更する:/e なし
    s/%(.)/$percent{$1} || $&/ge;        # これは式として評価する:/e あり
    s/^=(\w+)/pod($1)/ge;        # 関数呼び出しを使う

    $_ = 'abc123xyz';
    $x = s/abc/def/r;            # $x は 'def123xyz' となり、
                                 # $_ は 'abc123xyz' のままです

    # $_ の中で変数を展開する。
    # シンボリック・デリファレンスを使う。
    s/\$(\w+)/${$1}/g;

    # 文字列の中のあらゆる数字の値に 1 を加える
    s/(\d+)/1 + $1/eg;

    # 最後の 30 文字にある単語をタイトルケースにする
    # (部分文字列が単語の途中で始まらないと仮定)
    substr($str, -30) =~ s/\b(\p{Alpha})(\p{Alpha}*)\b/\u$1\L$2/g;

    # これは $_ の中に組み込まれたスカラー変数
    # (レキシカルを含む) を展開する:$1 はまず
    # 変数名に展開されてから評価される
    s/(\$\w+)/$1/eeg;

    # C 言語のコメント (のほとんど) を削除する
    $program =~ s {
        /\*        # 開始区切りに一致
        .*?        # 最小の文字数に一致
        \*/        # 終了区切りに一致
    } []gsx;

    s/^\s*(.*?)\s*$/$1/;        # $_ の中のホワイトスペースを取り除く
                                # ただし処理コストが高い

    for ($variable) {           # $variable の中のホワイトスペースを取り除く
                                # 処理コストは低い
        s/^\s+//;
        s/\s+$//;
    }

    s/([^ ]*) *([^ ]*)/$2 $1/;  # 最初の 2 つのフィールドを入れ替える

    $foo !~ s/A/a/g;    # $foo の中のすべての A を小文字にする
                        # 一つでも見つかって変更されれば 0 を返し、
                        # 見つからなければ 1 を返す

最後の例では \ の代わりに $ を使っている点に注意してください。 sed とは違い、左手側(PATTERN 側)でだけ \<数字> 形式を使っています。 それ以外のところでは $<数字> です。

ときどき、/g を使っただけでは、必要な変更をすべて発生させられない場合があります。 以下は、そのよくある例です。

# 整数の正しい位置にカンマを入れる
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g;

# Tab をスペースに変換して 8 文字幅にする
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;

s////c フラグを受け入れますが、 警告が有効な場合は、それは警告を発生させること以外に何ら効果をもたらしません。