Rubyをちょろっと始めました
いい加減「スクリプト言語はbashしか使えません」状態はヤバいなぁと思ってRubyをちょろっと始めました。まだ右も左も分かりません。
今日はpythonのrelpath関数みたいなのがRubyには見当たらないー!と思って自作してしまったのですが、実はPathname#relative_path_fromってのがあることが判明。早まりました。大ショック。
とりあえずRuby初心者がコーディングするとこうなる記録としてソース貼っておきます。文字列のスライス周りとかもっと奇麗に短くかける方法がある気がする…というかあるよね…。
!/usr/bin/ruby def normalize ( path ) ret = []; path += "/" if path.end_with?('.') || path.end_with?('..'); for e in "^#{path}$".split('/') do if e == '..' then ret.pop; elsif e != '.' && e != '' then ret.push(e); end end return ret.join('/')[1..-2]; end def rel_path ( dest, base ) base = normalize(base); dest = normalize(dest); sa = base.split('/'); da = dest.split('/',-1); i = 0; while i < sa.length && sa[i] == da[i] do i = i + 1; end if (sa[0]==''?1:0) < i then return '../' * (sa.length - i) + da[i..-1].join('/'); end return dest; end
Rubyは言語としてはすごくコンパクトかつきれいにプログラムが書けそうでいいなぁと思いましたが、ライブラリ類がちょっと違和感あり。"/a/b/c/".split('/') の結果が[ '', 'a', 'b', 'c', '' ]じゃなくて[ '', 'a', 'b', 'c' ]になるのがデフォなのはどうかなと思う。普通にCSVの解析とかで事故るような…ってやっぱ驚いてる人いますね。
で、テスト。
def test_rel_path(dest,base,expect) ret = rel_path(dest,base); puts "rel_path('%s','%s')='%s'" % [ dest, base, ret ]; if(ret!=expect) then puts "Error: expecting result=" + expect; end end test_rel_path('/etc/my.cnf', '/etc/', 'my.cnf'); test_rel_path('/etc/./my.cnf', '/etc/samba/../', 'my.cnf'); test_rel_path('/etc/my.cnf', '/etc/', 'my.cnf'); test_rel_path('/etc/my.cnf', 'etc/', '/etc/my.cnf'); test_rel_path('/var/log/httpd/httpd.conf', '/var/log', 'httpd/httpd.conf'); test_rel_path('/var/log/messages', '/var/log/httpd/','../messages'); test_rel_path('/var/log/messages', 'var/log/httpd', '/var/log/messages'); test_rel_path('var/log/messages', '/var/log/httpd', 'var/log/messages'); test_rel_path('/etc/cron.d/', '/var/log/httpd', '/etc/cron.d/'); test_rel_path('/etc/cron.d', '/var/log/httpd', '/etc/cron.d'); test_rel_path('var/bar/', 'var/log/httpd', '../../bar/'); test_rel_path('/var/log/messages', '/var/log/httpd/../', 'messages');
実行結果
rel_path('/etc/my.cnf','/etc/')='my.cnf' rel_path('/etc/./my.cnf','/etc/samba/../')='my.cnf' rel_path('/etc/my.cnf','/etc/')='my.cnf' rel_path('/etc/my.cnf','etc/')='/etc/my.cnf' rel_path('/var/log/httpd/httpd.conf','/var/log')='httpd/httpd.conf' rel_path('/var/log/messages','/var/log/httpd/')='../messages' rel_path('/var/log/messages','var/log/httpd')='/var/log/messages' rel_path('var/log/messages','/var/log/httpd')='var/log/messages' rel_path('/etc/cron.d/','/var/log/httpd')='/etc/cron.d/' rel_path('/etc/cron.d','/var/log/httpd')='/etc/cron.d' rel_path('var/bar/','var/log/httpd')='../../bar/' rel_path('/var/log/messages','/var/log/httpd/../')='messages'