Perlは、正規表現が深いレベルで統合されている言語の一つです。主な置換演算子はs///で、これはパターンに基づいて文字列の一部を検索して置き換えることを可能にします。この構文には多くの微妙な点が隠れており、特に貪欲および非貪欲なパターン、多行処理、および置換オプションを扱う際に重要です。
演算子s///はPerlの初期バージョンから存在しており、実際にPerlが正規表現の構文の基盤を築き、その後他の言語によって採用されました。パターンと修飾子(g、m、s、i、xなど)のほとんどのニュアンスは、正確にPerlで発展しました。
実際には、多くの開発者が貪欲な量指定子を不適切に使用したり、修飾子(特にsとm)を混同したりして、多行テキストや大きなデータでの置換時に予期しない結果を引き起こします。一つの期待される一致が得られない、または最初/最後の一致のみを置換することが原因でエラーが発生します。
パターンを正しく選択して設定し、修飾子の作用を理解することが重要です。貪欲なパターン(例えば、.*)は可能な限り最大の範囲をキャッチし、非貪欲なパターン(例えば、.*?)は必要最小限の範囲をキャッチします。
修飾子の取り扱い:
g — すべての一致に対して置換を実行します。s — 非貪欲モードを有効にし、点(.)が改行文字をキャッチできます。m — マーカー^および$の動作を変更します。例 — タグ<tag> ... </tag>を一度に一つのタグのみに置き換えます(非貪欲):
my $text = 'a <tag>1</tag> <tag>2</tag> b'; $text =~ s/<tag>.*?<\/tag>//g; print $text; # a b
複数行の文字列を処理するためには:
my $data = "Line 1 Line 2 <tag> DATA </tag> End"; $data =~ s/<tag>.*?<\/tag>//gs; print $data;
重要な特徴:
sは点(.)による改行のキャッチを可能にします。gは置換の回数に影響を与えます。*貪欲な.の後に?を指定しなかった場合、複数のタグを処理するとどうなりますか?
貪欲な量指定子は、最大の範囲をキャッチして中間のタグを含むため、最初の<tag>と最後の</tag>の間にあるすべてが予期せず削除されます:
my $txt = 'A <tag>1</tag> <tag>2</tag> B'; $txt =~ s/<tag>.*<\/tag>//g; print $txt; # A B
ここでは最初の<tag>と最後の</tag>の間のすべてが置換されました。
Perlの正規表現における修飾子mと修飾子sの違いは何ですか?
s — 点(.)が改行文字をキャッチします;m — 多行テキスト内での行の内側での動作のために^と$の動作を変更します。それぞれの目的は異なりますが、しばしば混同されます。
my $s = "abc def"; # /^def/はmなしでは機能しません print $s =~ /^def/m; # 1 (true)
s///を1回だけ適用してパターンのすべての出現を処理するにはどうすればよいですか?
修飾子gなしでは最初の一致のみが置換されます。グローバルな置換のためにはgを追加する必要があります:
my $s = "foo bar foo"; $s =~ s/foo/baz/g; # 両方のfooを置換
開発者はHTMLタグの置換を次のように記述します:
$text =~ s/<tag>.*<\/tag>//g;
結果として、すべてのタグとそれらの間のコンテンツが削除されます — それぞれを単独でではなく。
利点:
欠点:
非貪欲なパターンと適切な修飾子を使用します:
$text =~ s/<tag>.*?<\/tag>//gs;
利点:
欠点: