2009年10月20日火曜日

JavaScript と、Perl と、Groovy の split

ある文字でデータを分けて配列にするsplit。例えば JavaScirpt で
var text = "AAA<tag>BBB</tag>CCC";
var ary = text.split(/<.+?>/);
$.writeln(ary.toSource());
//ESTK の場合。 fireBug ならば console.log(ary);

["AAA", "BBB", "CCC"]
と表示される。
それが、splitの中で使う正規表現をキャプチャして
var ary = text.split(/(<.+?>)/);
とすると結果が
["AAA", "<tag>", "BBB", "</tag>", "CCC"]
と返る!このことを自分は今日まで知らなかった。

perlでも同じように返る。
my $text = "AAA<tag>BBB</tag>CCC";
my @ary = split(/(<.+?>)/,$text);
foreach $token(@ary){
print $token . "\n";
}
AAA
<tag>
BBB
</tag>
CCC

Rubyでも同じらしい。じゃあGroovyだと思い、
def text = "AAA<tag>BBB</tag>CCC"
def ary = text.split(/(<.+?>)/)
println ary
とやってみたが、
[AAA, BBB, CCC]
としか返らない。あれ?

Groovy の split は Java の split で、そういう風には使わないっぽい。
じゃあ tokenize では?
def text = "AAA<tag>BBB</tag>CCC"
def ary = text.tokenize(/(<.+?>)/)
println ary
[AAA, tag, BBB, /tag, CCC]
……。
タグの<>がなぜか外れてしまう。むー、よくわからん……。


10月21日追記。
Groovy の ソースの tokenize を読んでみた。DefaultGroovyMethods.java の 6627 行目あたりに
public static List tokenize(String self, String token) {
return InvokerHelper.asList(new StringTokenizer(self, token));
}
つまり、渡された引数が String でも GString でも、そのまま StringTokenizer に渡して List で返しているわけか。(ただの区切り文字の集まりとして読んでいるから、< と > がひっかかって分割されて、< > 自体は消えている)
GString でキャプチャされてた時にデリミタを返すのは難しいにしても、だったら tokenize(String, Boolean) でトークンを返すのは欲しいなぁ。

0 件のコメント: