非破壊な s/// のススメ

正規表現の置換でときどき困るのは、元の文字列が変更されてしまうことです。そのため、たとえば文字列を URI escape する際には、以下のように別変数にコピーした上で、正規表現を適用することになります。

my $escaped = $search_str;
$escaped =~ s/([^0-9A-Za-z_.!~*'()-])/'%' . uc(unpack('H2', $1))/eg;
my $url = "http://example.com/search?q=$escaped";

以前、この点がめんどくさいなーとブログに書いたところ、kazeburo さん他に以下のようなテクニックを教えていただきました。

use List::MoreUtils qw(apply);

my $url = 'http://example.com/search?q='
    . apply { s/([^0-9A-Za-z_.!~*'()-])/'%' . uc(unpack('H2', $1))/eg } $search_str;

これなら、不要な変数に頭を悩まされずに1ステートメントで書くことができ、意味も明快です。いいですね。

次は id:amachang。