〜2013年10月中旬〜
akrさんからmake-standalone-toolchain.shすれば--sysroot不要との情報を得た。
% $NDK_ROOT/build/tools/make-standalone-toolchain.sh --install-dir=$HOME/android/arm-linux-androideabi
として、PATHに$HOME/android/arm-linux-androideabi/binを加えればok。
rubyはtrunkを使うのでtrunk版rubyもインストールしておく。
あとはこんな感じで。
% trunk=/some/where/ruby/trunk % mkdir trunk-android % cd trunk-android % ac_cv_func_getpgrp_void=yes ac_cv_func_setpgrp_void=yes \ $trunk/configure \ --target=arm-linux-android --host=arm-linux-androideabi --build=i686-linux \ -C --disable-rubygems --prefix=/data/local/tmp/ruby % make main % make DESTDIR=/tmp/dest install-nodoc % arm-linux-androideabi-strip --strip-unneeded /tmp/dest/data/local/tmp/ruby/{bin/ruby,lib/**/*.so} % rm /tmp/dest/data/local/tmp/ruby/lib/libruby-static.a % tar cfvz ~/ruby-android.tar.gz -C /tmp/dest/data/local/tmp ruby % ls -oh ~/ruby-android.tar.gz -rw-r--r-- 1 eban 4.5M 2013-10-11 21:23:46 /home/eban/ruby-android.tar.gz % adb push ~/ruby-android.tar.gz /data/local/tmp
あとはadb shellでtarballを展開すればいいが、tarがないのでbusyboxを使う。
Index of /downloads/binaries
% wget http://www.busybox.net/downloads/binaries/1.21.1/busybox-armv7l % chmod +x busybox-armv7l % adb push busybox-armv7l /data/local/tmp % adb shell /data/local/tmp/busybox-armv7l tar xfv /data/local/tmp/ruby-android.tar.gz -C /data/local/tmp % adb shell /data/local/tmp/ruby/bin/ruby -v ruby 2.1.0dev (2013-10-11 trunk 43254) [arm-linux-android]
できあがり。
本家からもろもろダウンロードしてもいいが、
Ubuntuならもっと簡単にandroid-tools-adbをインストールすればok。
あとはdeviceに合わせて/lib/udev/rules.dの下に設定ファイルを用意する。
/var/log/syslogかlsusbコマンドでidVendorを確認すればいい。
% lsusb | grep Google Bus 002 Device 008: ID 18d1:4e41 Google Inc. % echo 'SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"' | sudo tee /lib/udev/rules.d/51-android.rules SUBSYSTEM=="usb", SYSFS{idVendor}=="18d1", MODE="0666"
これでdeviceをつなげばadbが使えるようになる。
% adb devices * daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached 015d256851181c0e device
permissionがどうのうこうの出るときはkill-serverしてsudoで。
% adb devices * daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached ???????????? no permissions % adb shell error: insufficient permissions for device % adb kill-server % sudo adb start-server % adb devices * daemon not running. starting it now on port 5037 * * daemon started successfully * List of devices attached EP7321C0J4 device
いったいどうなっているのか?
% adb shell /data/local/tmp/ruby/bin/ruby -e 'puts "Hello, world!"' -e:1: syntax error, unexpected end-of-input
これじゃわからないのでARGVを使って表示してみる。
% adb shell /data/local/tmp/ruby/bin/ruby -e 'p ARGV' -- -e 'puts "Hello, world!"' ["-e", "puts Hello,", "world!"]
かなり予想外だ。まあ、これじゃsyntax errorになるわけだ。ソース探して見てみるか。
Reader Storeで買った書籍をタイトル順でソートすると謎の順番になるが、
何の順番かやっとわかった。シリーズ物14冊の場合。
タイトル1 タイトル9 タイトル5 タイトル3 タイトル10 タイトル11 タイトル13 タイトル12 タイトル14 タイトル7 タイトル2 タイトル8 タイトル4 タイトル6
いち、きゅう、ご、さん、って数字を50音順で並べてたんだな。1枚クイズか。
ってそんなソートされて誰が喜ぶのか。
マジコメで対応可能。
% cat > foo.rb if true p :hoge end % ruby -w foo.rb foo.rb:3: warning: mismatched indentations at 'end' with 'if' at 1 :hoge % echo '# -*- warn-indent: false -*-' | cat - foo.rb > bar.rb % cat bar.rb # -*- warn-indent: false -*- if true p :hoge end % ruby -w bar.rb :hoge
こんな感じで # -*- warn-indent: false -*- を入れればいい。defaultはtrueになっている。
何度でも使えるのである範囲内だけ黙らせることも可能。
実はindentのcheckは対応するものだけしか見てない。
その中身のindentがどうなっていようが関係ない。
% cat foo.rb if true p :hoge p :hoge end % ruby -w foo.rb :hoge :hoge
行番号つけてsort -nrして行番号を外すのが簡単かな。
nl -ba -s:|sort -nr|sed 's/[^:]*://'
-baしないと空行に番号がつかない。
区切りはタブのままでもいいが、BSDのsedは\tが使えないので生のタブを使うことになる。
sort -sk0.0,0.0rでいけるかと思ったが、さすがに0は受け付けてくれなかった。
幅0で全部同じものとしてソートするがstableなのでそのままになり-rで逆順にする作戦。
まあ、そもそも-sをつけると-rが無効になるようなので全然だめだめなんだけど。
2年ぐらい見てて思ったんだけど、順位に変動はあっても毎週ほとんど同じ曲がランクインしてる気がする。
どんなもんか調べてみるかとweb page見に行ったら、なんとTSV形式でデータが置いてあった。
やるなM-ON!。
過去2年分ぐらいを取ってくるスクリプトを作るか。
残念ながら過去30週のデータしか残ってなかった。
データをダウンロードするスクリプトはこんな感じ。
例によって\Kを使ってgrepで抜き出している。
(追記) やっぱりやめて抜き出したものをそのまま使うようにした。
あと
-Jオプションが大事。
% cat m-on.sh #! /bin/bash base='http://www.m-on.jp' cd20='chart/karaoke-countdown20' tsv='chart/download' path=$cd20 for i in {1..50}; do echo "$base/$path/" ids=($(curl -s "$base/$path/" | grep -Po "chart/(karaoke-countdown20|download)/\d+")) curl -JORC- "$base/${ids[0]}/" path="${ids[1]}" if [ -z "$path" ]; then echo no data break fi done % ls *.tsv karaoke-countdown20_20130320.tsv karaoke-countdown20_20130605.tsv karaoke-countdown20_20130814.tsv karaoke-countdown20_20130327.tsv karaoke-countdown20_20130612.tsv karaoke-countdown20_20130821.tsv karaoke-countdown20_20130403.tsv karaoke-countdown20_20130619.tsv karaoke-countdown20_20130828.tsv karaoke-countdown20_20130410.tsv karaoke-countdown20_20130626.tsv karaoke-countdown20_20130904.tsv karaoke-countdown20_20130417.tsv karaoke-countdown20_20130703.tsv karaoke-countdown20_20130911.tsv karaoke-countdown20_20130424.tsv karaoke-countdown20_20130710.tsv karaoke-countdown20_20130918.tsv karaoke-countdown20_20130501.tsv karaoke-countdown20_20130717.tsv karaoke-countdown20_20130925.tsv karaoke-countdown20_20130515.tsv karaoke-countdown20_20130724.tsv karaoke-countdown20_20131002.tsv karaoke-countdown20_20130522.tsv karaoke-countdown20_20130731.tsv karaoke-countdown20_20131009.tsv karaoke-countdown20_20130529.tsv karaoke-countdown20_20130807.tsv karaoke-countdown20_20131016.tsv % iconv -fcp932 karaoke-countdown20_20131016.tsv 順位 前週 動き 曲名 アーティスト 1 1 stay 恋するフォーチュンクッキー AKB48 2 2 stay 女々しくて ゴールデンボンバー 3 3 stay ハナミズキ 一青 窈 4 4 stay 栄光の架橋 ゆず 5 5 stay キセキ GReeeeN 6 6 stay チェリー スピッツ 7 7 stay 天体観測 BUMP OF CHICKEN 8 9 up 366日 HY 9 8 down Story AI 10 10 stay 奏(かなで) スキマスイッチ 11 19 up 愛をこめて花束を Superfly 12 up 雪の華 中島美嘉 13 12 down ヘビーローテーション AKB48 14 14 stay 純恋歌 湘南乃風 15 16 up シングルベッド シャ乱Q 16 17 up 愛のうた 倖田來未 17 18 up 睡蓮花 湘南乃風 18 13 down 愛唄 GReeeeN 19 22 up 三日月 絢香 20 23 up I LOVE YOU 尾崎豊
これを全部まとめて順位は無視してカウントする。
% cat *.tsv | iconv -fcp932 | cut -f4,5 | grep -v $'^曲名\t' | sort | uniq -c | sort -nr | nl 1 30 純恋歌 湘南乃風 2 30 栄光の架橋 ゆず 3 30 女々しくて ゴールデンボンバー 4 30 ヘビーローテーション AKB48 5 30 ハナミズキ 一青 窈 6 30 チェリー スピッツ 7 30 キセキ GReeeeN 8 30 Story AI 9 30 366日 HY 10 29 愛唄 GReeeeN 11 29 愛のうた 倖田來未 12 29 天体観測 BUMP OF CHICKEN 13 25 シングルベッド シャ乱Q 14 23 睡蓮花 湘南乃風 15 17 花火 三代目J Soul Brothers 16 13 行くぜっ!怪盗少女 ももいろクローバー 17 12 奏(かなで) スキマスイッチ 18 12 フライングゲット AKB48 19 12 RPG SEKAI NO OWARI 20 11 桜 コブクロ 21 11 スターラブレイション ケラケラ 22 11 I LOVE YOU 尾崎豊 23 10 道 EXILE 24 9 夏祭り Whiteberry 25 9 3月9日 レミオロメン 26 7 最後の雨 中西保志 27 7 インベーダーインベーダー きゃりーぱみゅぱみゅ 28 6 涙そうそう 夏川りみ 29 6 恋するフォーチュンクッキー AKB48 30 6 夏色 ゆず 31 5 三日月 絢香 32 5 にんじゃりばんばん きゃりーぱみゅぱみゅ 33 4 島人ぬ宝 BEGIN 34 4 さくら ケツメイシ 35 4 SUMMER NUDE '13 山下智久 36 3 粉雪 レミオロメン 37 3 桜坂 福山雅治 38 3 会いたくて 会いたくて 西野カナ 39 2 愛をこめて花束を Superfly 40 2 Lovers Again EXILE 41 1 雪の華 中島美嘉
うむ。やはりカラオケはあまり変化しないんだな。30週連続が9曲もある。
bashとzshでは配列のインデックスの始まりが違う。
% bash -c 'foo=(a b c);echo ${foo[0]}' a % zsh -c 'foo=(a b c);echo ${foo[1]}' a
使ってて1から始まるのは結構使いづらい。
大抵こういうときはksh_なんとかってやつでsetoptできるようになってる。
この場合はksh_arraysだ。
% zsh -c 'setopt ksh_arrays;foo=(a b c);echo ${foo[0]}' a
これで0から始まるようになる。
ソースを見たら引数に空白が含まれていたら、その引数を""で囲むという処理になっていた。
だからさらに"が含まれていたら当然おかしなことになる。なんとも中途半端だな。
% adb shell /data/local/tmp/ruby/bin/ruby -e 'puts "Hello, world!"' -e:1: syntax error, unexpected end-of-input
これは以下のように実行したのと同じ結果になる。
% sh -c 'ruby -e "puts "Hello, world""' -e:1: syntax error, unexpected end-of-input
環境変数ABD_TRACEで一応確認できる。
rubyじゃなくても同じなのでechoで
% ADB_TRACE=1 adb shell echo 'puts "Hello, world!"' adb.c::main():Handling commandline() commandline.c::adb_commandline():interactive shell loop. buff=shell:echo "puts "Hello, world!"" adb_client.c::_adb_connect():_adb_connect: host:version transport.c::writex():writex: fd=3 len=4: 30303063 000c transport.c::writex():writex: fd=3 len=12: 686f73743a76657273696f6e host:version transport.c::readx():readx: fd=3 wanted=4 transport.c::readx():readx: fd=3 wanted=4 got=4 4f4b4159 OKAY adb_client.c::_adb_connect():_adb_connect: return fd 3 adb_client.c::adb_connect():adb_connect: service shell:echo "puts "Hello, world!"" transport.c::readx():readx: fd=3 wanted=4 transport.c::readx():readx: fd=3 wanted=4 got=4 30303034 0004 transport.c::readx():readx: fd=3 wanted=4 transport.c::readx():readx: fd=3 wanted=4 got=4 30303166 001f adb_client.c::_adb_connect():_adb_connect: shell:echo "puts "Hello, world!"" transport.c::writex():writex: fd=3 len=4: 30303132 0012 transport.c::writex():writex: fd=3 len=18: 686f73743a7472616e73706f72742d61 host:transport-a adb_client.c::switch_socket_transport():Switch transport in progress transport.c::readx():readx: fd=3 wanted=4 transport.c::readx():readx: fd=3 wanted=4 got=4 4f4b4159 OKAY adb_client.c::switch_socket_transport():Switch transport success transport.c::writex():writex: fd=3 len=4: 30303231 0021 transport.c::writex():writex: fd=3 len=33: 7368656c6c3a6563686f202270757473 shell:echo "puts transport.c::readx():readx: fd=3 wanted=4 transport.c::readx():readx: fd=3 wanted=4 got=4 4f4b4159 OKAY adb_client.c::_adb_connect():_adb_connect: return fd 3 adb_client.c::adb_connect():adb_connect: return fd 3 commandline.c::adb_commandline():about to read_and_dump(fd=3) commandline.c::read_and_dump():read_and_dump(): pre adb_read(fd=3) commandline.c::read_and_dump():read_and_dump(): post adb_read(fd=3): len=20 puts Hello, world! commandline.c::read_and_dump():read_and_dump(): pre adb_read(fd=3) commandline.c::read_and_dump():read_and_dump(): post adb_read(fd=3): len=0 commandline.c::adb_commandline():read_and_dump() done. commandline.c::adb_commandline():interactive shell loop. return r=0
echo "puts "Hello, world!"" となっている。
以上のことから
% adb shell /data/local/tmp/ruby/bin/ruby -e 'puts \"Hello, world!\"' Hello, world!
とすればいいわけだけど、わかりにくい。""が出てこないように常に%q()とかを使うのはありだな。
% adb shell /data/local/tmp/ruby/bin/ruby -e 'puts %q(Hello, world!)' Hello, world!