変換演算子 tr///

変換演算子 tr/// は、文字列を対象に「ある文字からある文字へ」と変換する時に利用する演算子です。検索や置換と同じように文字列に対して =~ 演算子を使って適用します。
tr/// 演算子には2つの「文字のリスト」をスラッシュ(区切り文字は変更可能)で区切って渡します。1つめのリストは「検索リスト」で、2つめのリストは「置換リスト」と呼ばれるそうです。置換演算子 s/// と似ていますが、非なるものです。
例えば

my $text = "ABCDABCD";
$text =~ tr/BD/bd/;
print $text;

このコードでは「検索リスト」に「BD」、「置換リスト」に「bd」を指定しています。
実行すると、このように表示されます。

AbCdAbCd

変換の対象となった文字列を1文字ずつスキャンしていき、もしその文字が検索リストに含まれていたら、対応する置換リストの文字に置き換えてくれます。
ここで重要なのは、「2つのリストが対応関係にある」という事ですね。(^_^) 文字の対応を決めるのには「リスト内での順番」が使われます。2つのリスト中の同じ位置にある文字が対応関係になります。
上のコードの場合、「B」と「b」、「D」と「d」がそれぞれ対応している事になりますね。大文字小文字は厳格に区別されます。その結果「変換」されて、それぞれ置き換えられました。
s/// 演算子では、置換の単位となるのは「文字列」でしたが、tr/// 演算子では置換の単位は「文字」というわけですね。(^_^)


文字リストは正規表現ではありませんが、「-」(ハイフン)を使って範囲を表す事ができます。角カッコ [ ] は必要ありません。

tr/A-Z/a-z/

と書いた場合、「大文字のAからZ」が「小文字のaからz」に変換されます。(文字列を小文字にする lc 関数と同じ効果ですね)

tr/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

と等価です。


ところで、検索リストに対して置換リストの文字数が少なかったらどうなるのでしょうか。文字の対応関係が崩れてしまいます。という事で試してみました。

my $text = "ABCDABCD";
$text =~ tr/ABC/ab/;
print $text;

変換リストが「ABC」と3文字あるのに対し、置換リストは「ab」の2文字だけです。「C」に対応する文字がありません。
実行するとこのようになりました。

abbDabbD

「C」は「b」に変換されているので、どうやら足りない分は置換リストの最後の文字が使われるようですね。
ではでは、置換リストが空だとどうなるのでしょうか。

my $text = "ABCDABCD";
$text =~ tr/ABC//;
print $text;

実行してみると……

ABCDABCD

ありゃりゃ。変換されませんでした。(^_^;) 検索リストの文字が消えるかと思ったのですが、s/// 演算子とは違い、空のリストを指定すると実行されないようです。これは注意した方が良さそうですね。


tr/// 演算子のオプションの勉強はまた明日♪