2006-09-13

(追記あり。)

問い:
別のところで定義されている文字 $A, $B があったとする。文字列 $s 中にある $A をすべて $B に置き換えたい。Perl でこれを処理するにはどう書けばよいでしょう。

$A, $B というのはようするにグローバル変数です。

さて、$A, $B が文字なので、文字を入れ替える tr 演算子を使うだろう、と考えるわけです。

$s =‾ tr/$A/$B/;

ブー。これはうまくいかない。tr 演算子は変数展開をしない。なんなんだこれは。$s =‾ tr/X/Y/; と書いて XXXYYY にすることはできるけど、$X = "X"; $Y = "Y"; tr/$X/$Y/; はできない。どうするのかというと、こうしろと。

eval "¥$s =‾ tr/$A/$B/;";

ありえん。eval て。個人的には eval というのは最後の手段的なものだと思ってましたが。デバッグできないし。しかもこれは正しく動かない。$A‘/’$B‘Y’ だったらどうなりますか。eval されるのは “$s =‾ tr///Y/;” というわけでエラーになります。

なので事前に文字をエスケープする必要があります。$A, $B はグローバル変数なので勝手に置換してしまうわけにはいかないので、ローカルにコピーして使います。

my $a;
my $b;
($a = $A) =‾ s/(¥¥|¥/)/¥¥$1/g;
($b = $B) =‾ s/(¥¥|¥/)/¥¥$1/g;
eval "¥$s =‾ tr/$a/$b/;";

これでいちおう正解(のはず)。たのしいね。

こんなのやってられないので正規表現置換することにします。s 演算子は変数展開もしてくれるし。

$s =‾ s/$A/$B/g;

もちろんこれもアウト。今回は $A ないし $B‘¥’ だと正規表現のメタ文字として解釈されておかしなことになります。というわけでエスケープ。今回も $A, $B はローカルにコピーします。

my $a;
my $b;
($a = $A) =‾ s/¥¥/¥¥¥¥/g;
($b = $B) =‾ s/¥¥/¥¥¥¥/g;
$s =‾ s/$a/$b/g;

これで正解(のはず)。ぜんぜん行数減ってない。

追記。

上のコードは間違っていました。$B‘¥’ のときに間違った結果になります。正しくは以下のようにする必要がある。

my $a;
($a = $A) =‾ s/¥¥/¥¥¥¥/g;
$s =‾ s/$a/$B/g;
$s;

エスケープ処理するのは $A のほうだけでいい。置換文字列のほうは正規表現じゃないからか。なんか正規表現リテラルがあるとかえって混乱するな……。

‘X’‘¥’ に置換。 ‘¥’‘X’ に置換。
直接指定 変数を経由 直接指定 変数を経由
Perl
$s =‾ s/X/¥¥/;
$a = "X";
$b = "¥¥";
$s =‾ s/$a/$b/;
$s =‾ s/¥¥/X/;
$a = "¥¥¥¥";
$b = "X";
$s =‾ s/$a/$b/;
Python
re.sub('X', '¥¥', s)
a = 'X'
b = '¥¥'
re.sub(a, b, s)
re.sub('¥¥¥¥', 'X', s)
a = '¥¥¥¥'
b = 'X'
re.sub(a, b, s)
TX-C(笑)
regular(s, "X", "¥¥", 0);
a = "X";
b = "¥¥";
regular(s, a, b, 0);
regular(s, "¥¥¥¥", "X", 0);
a = "¥¥¥¥";
b = "X";
regular(s, a, b, 0);

↑これでよい? 強調部分の非対称性が罠か。

さて、Perl で正規表現のエスケープに使うメタ文字、¥Q, ¥E中村さんから教えてもらいました。

$s =‾ s/¥Q$A¥E/$B/g;

ありがとうございました。これがどうも Perl での「いちばん正しい」書きかたみたいですね。

じつはもうひとつ、1行で書けるのも考えました。

join '', map { $_ eq $A ? $B : $_ } split //, $s;

でもこれはかなり遅いみたいです。それにべつにわかりやすいわけでもありませんし。

ところでこの処理を Python で書くとこうなります。(べつに Python でなくてもまともな文字列操作メソッドがある言語ならおんなじでしょうけど。)

s.replace(A, B)

あと Perl でもっと簡単に書ける方法をご存知の方は教えていただけるとありがたいです(というか単純な replace はないのでしょうか)。

2006-09-11

雑談。

なんで Perl の Getopt なんかを調べたかというと、ftpsite.pl に手を入れているのでした。忙しいので一日にほんの少しずつしか進めてないけど、息抜きです。

もう二年以上も前に書いたきりのスクリプト。いま見ると冗談抜きで「これはひどい」といいたくなるような書き方だ。恥ずい。書いていた当時は大真面目だったはずなのですが。これは二年間で成長しているということなのか、それともたんに書く能力がないだけなのか……。

正直なところもう Perl は書きたくなかったので、うっかり ftpsite.py に取り掛かりかねない勢いだったのですが、ここはあえて思いとどまることに。また、書いたのがもう二年前ということで「最初から書き直したほうがいいかも」という誘惑も強かったのですが、それも制止。Perl のまま、古いコードに手を入れる方式で改良してみることにしました。なんとなく、たまにそういうこともしないと技術が向上しないような気がしたので……。

ひさしぶりに書く Perl。もうセミコロン忘れる忘れる。print 文の末尾に "¥n" を忘れる忘れる。

でもなんとかリファクタっぽいことができました。旧コードから始めたけど、その面影は現在はほとんどなくなっている。途中あたりから面白くなってきますね。やっぱり最初から書き直さなくてよかったと思いました。

あと Python がいかにまともかを思い知りました。

2006-08-27

更新情報

Perl での Getopt::Long モジュールの使い方についてのメモ、「Perl スクリプトでのコマンドラインオプション処理」を書きました。Getopt、Python では使ってたのですが、Perl のほうはいまいちやり方がわかってなかったので。

Python の getopt モジュールはドキュメントの「getopt — コマンドラインオプションのパーザ」がわかりやすいです。

こうして両者を比べてみると、同じ機能でも実装にその言語らしさが如実に出ていておもしろい。暗黙的な Perl と明示的な Python。–nohoge のサポートなんかは Python プログラマからしたら変態的に見えるだろうし、短縮形のオプションや型変換まで明示的にやらなければいけない getopt 関数は Perl プログラマからすると融通が利かないということになるのでしょうか。

Alt + Home

先日の某所オフにて、ThinkPad X60s を中村さんに見せてもらっていて、なにげなく「(キーボードの)右Alt がないと、Alt + Home しにくいですね」と言ったら「???」という反応をされてしまった。ウェブブラウザで Alt + Home(ホームに戻る)、あんまり知られてないのかしらん。

僕はブラウザのホームを Google にしているのですが、そうしてブラウズ中に検索したいことができたら「Alt + Home を押す」→「検索語入れて検索」というのが日常になっていたのです。で、右 Alt があったら Alt + Home が右手だけでできるじゃないですか(左 Alt + Home も同じくらい使うけど)。

あんまり有名じゃないみたいですが、特定のページに一跳びできるキーボードアクションなんて貴重ですよ、ということで、うまい使い方を思いつく人もいるかと思って書いてみました。

2006-07-26

(今日のは雑談です。)

提携発表の時点でなんとなくいやな予感はしてたけど、やっぱりLast.fmの日本版は残念な展開で始まった。ラジオ聞けないんだって。それで「FM」はないよ。ラジオは今秋開始を目指してるそうなので、その点ばかり非難するのは早まってるのかもしれないけど、「Love/Banできるラジオ」というのがLast.fmのキモなんだから(それをコピーにもしてたし)。

提携発表時の

“俺ラジオ”作れる「Last.fm」が日本進出

あなたが好きそうな楽曲を探し出し、ラジオのように流してくれる――英国生まれのそんなサービスの日本版が今夏オープンする。その名も「Last.fm」。最後に行き着くFM局、という意味だ。

というのが

音楽SNS「Last.fm」日本版がオープン

PCの楽曲再生リストを共有でき、おすすめ楽曲を教えてくれる「Last.fm」日本版が公開された。

ではずいぶん印象が違う (ITmedia)。プレスの人がすごく気を使った表現をこしらえたに違いない。

Last.fmのプレーヤーも日本版はラジオ再生機能がない。なにそれ。黙々と曲名にタグとか付けてむなしいひとり遊びをするためのおもちゃです(←言い過ぎ)。

サイトの翻訳は行き届いているので、本家(英語版)と同じスペックで日本語UI版というだけならよかったのに。

いや、それよりもなによりも、これまで本家を利用していた日本のユーザーを問答無用で(ラジオ機能のない)日本版にリダイレクトしたというのが気に入らない。そしてそのこと(本家にある一部の機能がないこと、そしてそもそもリダイレクトしたこと)についてどこにも説明がない(リダイレクトしたというのは僕はImpress Watchの記事で読んで知った)。このときばかりは売られたとすら思いましたぜ。やさぐれてるのはそのせいです。

ページの左下に言語切り替えのリンクがあったのでこれを “English” にしたら本家の体裁に戻りました。

スクリーンショット: ページ左下の言語切り替えのリンク

すでに英語版のLast.fmのプレーヤーを使っている人は、わざわざラジオ機能のない日本版プレーヤーに乗り換える意味はありません。というか、ラジオが聞けるまで日本版は単なるだらしのないSNSに過ぎません。英語版でもUIが英語になってるだけで日本語は使えるので、いますぐ始める人は英語版でやろうね。エキサイトの中の人は、SNSなら日本人は適当にグルーミングしあって喜んでくれるからちょろいぜとか考えてませんか。そんなことないですか。だといいですけど。

(なんかどうしても、音楽サービスというよりはエキサイトが出来合いのSNSプラットフォームと日本地域のユーザーをカネで買ったという印象しか持てないんですよね……。心がピュアじゃないから? ちがう。いままでLast.fmを利用していた日本のユーザーへの説明(どうやったらまたラジオが聞けるようになるのか、など)がないからだ。)

個人的にも、日本版でラジオが始まったって、流す楽曲について日本版が独自に契約を結んでいくのなら、僕の好きなアーティストの曲が流れるようになるのは遠い先の話に違いない。そういう意味でも自分はとうぶん本家英語版だなあ。

そういえば、エキサイトIDの人は英語版にしたらラジオが聞けるようになるんだろうか。

2006-06-22

1年以上前に遊びで作ってみたマクロを公開します。僕はもうメンテしないけど、このまま捨てるのはなんとなくもったいないような気がしたので……。

WZ の正規表現検索をなんとかする(?)

WZ の正規表現検索は完成度があまり高くありません(1年以上前も、いまも)。そこで、TRE というオープンソースの POSIX 準拠の正規表現ライブラリを利用するマクロを作ってみました(1年以上前に)。

tretx 0.10 – WZ で TRE 正規表現ライブラリを利用する
http://www.emptypage.jp/download/tretx-0.10.zip

詳しくは同梱しているドキュメントを(これも殴り書きですが)ご参照ください。

そしてどなたか本体と置き換えて使えるくらいにまでブラッシュアップしてください。

あ、マクロで指定する正規表現は(当然ですが)WZ のそれではなくて TRE のドキュメントにある仕様で指定してくださいね。