2008/07/17(Thu)変数の展開の展開

2008/07/17 4:21 Languages::Perl
文字列処理にPerlほどすぐれた言語はない……と考えている今日この頃だが、ちょっとハマったので解決策をメモ。

やりたいこと

「何らかの処理の結果、ある文字列が得られたとする。その文字列と同じ名前の変数名を取得したい」

具体的には、リソースファイルに"この結果は$resultになります"のように埋め込んでおき、スクリプト実行時に変数$resultを代入して、"この結果は25になります"のように表示させたいわけだ。

今まで使っていた手法

リソースファイルをPerl化してしまってrequireすれば、同じ名前空間の変数で、すでに定義されているものは自動展開されるという仕様を使っていた。
埋め込む変数名ごとに正規表現で置換するような面倒な手法に比べると楽にできていたのだが、Perl化する手間とフォーマットが崩れるのが欠点。
拡張子がplになってしまうので*1、HTMLファイルのテンプレートを書いていたところで、vimなんかで読み込むとPerlの色づけしかしてくれなくて不便なのである。


実際どんな手順かというと、リソースファイルとして、
#!/usr/local/bin/perl

# requireされるとき自動展開するためにダブルクォートにしておく
$tmp = << "_EOM_";
この結果は$resultになります
_EOM_

# requireのため、1;は削除できない(結構面倒な仕様)
1;
という代入だけを行うスクリプトを別途用意し、
呼び出し側として、
#!/usr/local/bin/perl

$result = 5*5;
require 'resource.pl';
print $tmp;
のような手順を踏まなくてはいけない。自動展開されるとはいえ、結構めんどい。
また、$tmpや$resultという変数名は両ファイルで合わせておかなくてはならず、use strictとか付けると変数宣言の問題で面倒な事に。

*1 : そりゃ.htmlとか付けてもいいけど、中身perlだしね…不適切。

どうしたかというと

なんとか引数に指定した変数を展開できないかなぁと思って調べていたら、evalなんてコマンドがあった。
存在は知ってたけど、いまいち使いどころが分からなかったヤツ。

これを使うと実にスマートに書ける。
#!/usr/local/bin/perl

# シングルクォート囲みなのでこの時点では展開されないことに注意
$tmp = q|この結果は$resultになります|;
$result = 5*5;
$tmp =~ s/(\$\w+)/eval($1)/eg;
print $tmp.qq|\n|;
この書き方のポイントは、
  • $resultのような展開したい変数がいくつあっても動作すること
  • requireの必要がないこと = requireを使う場合の煩雑さがない
  • 展開する変数への代入を、読み込み後に行えること(requireの場合は、結果が先に分かってからrequireしないと代入されない)
  • (use strict環境下で小細工しなくても普通に動く)
注意として、↑のマッチングだと変数名のすぐ後に英数字が来ると誤爆するので、${result}のような形式のものだけ反応させるようにとか、適宜工夫することを推奨。

2008/05/27(Tue)JavaApplet Trouble

2008/05/27 15:09 Languages::Java
Javaアプレットを書いていたのだけど、その検証作業でいろいろトラブったのでメモ。

「異なるバージョンのJavaが必要です。異なるバージョンのセッションを再ロードしますか?」

インストールされているJREが古いと出るようだ。Version 6 Update 6にしたら直った。
(正確なメッセージは忘れた)

IEでは動くアプレットが、Sleipnirでは灰色の塗りつぶしにしか表示されない

Sun Javaをインストールしても、SleipnirがMicrosoftのプラグインを使うことが原因らしい。
regsvr32 /u msjava.dllと実行してDLLレジストを解除してから、ブラウザを再起動すればよい。
これでも動かない場合は、インターネットオプションの詳細設定の中で、「<applet> に Java 2 v1.x.x_xx を使用(再起動が必要)」にチェックがついているかどうかチェック。

FreeBSDのappletviewerが文字化けする

メニューとステータスバーが豆腐になっていた。
appletviewerを起動するとき、-encoding EUC-JPをくっつけて起動すればよい。

2008/05/25(Sun)java on Fedora

2008/05/25 19:34 Languages::Java
JDKが必要になったので鯖に入れてみたのだけど、Hello Worldでコケたのでメモ。
初歩的なことなのだけど。

インストール

jdk-6u6-linux-i586-rpm.binとかを手に入れてきて、実行権限を付けてrootで実行してやればいい。
最初に規約に同意するためにyesって打つ位か。お手軽~。

設定

問題はここから。標準ではGNUのjavaがパスに指定されており、Sunのjavacでコンパイルしたものをjavaコマンドで実行するとjava.lang.ClassFormatError (unrecognized class file version)が発生する。
$ java -version
java version "1.5.0"
gij (GNU libgcj) version 4.1.2 20070925 (Red Hat 4.1.2-27)

Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
解決法は以下のとおり
$ sudo /usr/sbin/alternatives --install /usr/bin/java java /usr/java/jdk1.6.0_06/bin/java 2
$ sudo /usr/sbin/alternatives --config java

2 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.5.0-gcj/bin/java
   2           /usr/java/jdk1.6.0_06/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2
$ java -version
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) Client VM (build 10.0-b22, mixed mode, sharing)
これでおっけー!

実行方法

hogehoge.javaというソースをjavacでコンパイルするとhogehoge.classというのが出来るのだが、実行時は
$ java hogehoge.class
ではなく
$ java hogehoge
だそうだ。


とりあえずこんな所かな。