12

12

[Ruby] 仕事で使うRuby

2011.12.12(19:50)

Ruby(ルビー)は、島根県在住のまつもとゆきひろ(通称Matz)さんにより開発されたオブジェクト指向スクリプト言語です。フリーソフトウェアで誰でも使うことができます。

Rubyはインタプリタ言語で、テキストで書かれたソースコードを1行ずつ読み込んで実行します。日本語も使えます。基本的にユーザーインターフェースがない、コマンドラインで動作するプログラムを作るのに向いています。

私とRuby
  • ユーザー歴6年くらい。
  • 1行~100行ぐらいのプログラム作成に使っています。
  • 毎日毎日うんざりする仕事を片付けるのに。そのほか
  • ネットワークプログラムの開発に
  • WindowsでもMacでも同じプログラムを動かしたい時に
  • Jenkinsで起動するプログラムの開発に
  • オブジェクト指向プログラミングの勉強に
  • 関数型プログラミングの勉強に
  • メタプログラミングの勉強に


どんなことができるのか
  • テキストデータの処理、文字列を加工したり、並べ替えたり、ソートしたり
  • 数値計算
  • 整数計算、浮動小数点計算、行列演算
  • ファイルの読み書き
  • ネットワークからファイルをダウンロード
  • XMLやHTMLファイルの解釈

基本機能を拡張するライブラリがたくさん開発されていて、それもフリーで使えます。

どんなライブラリがあるのか (私が愛用しているもの)
  • 正規表現 (標準)
  • 配列、ハッシュ (標準)
  • ファイルの読み書き (標準)
  • Excelファイルの読み書き win32ole
  • Csvファイルの読み書き csv
  • 自動ドキュメンテーション作成 yardoc
  • 行列演算 matrix
  • Webからファイルをダウンロード mechanize, net/http
  • Zipファイルの圧縮解凍 zlib
  • HTTPサーバ、プロキシーサーバ WEBrick
  • ツイッタークライアント、認証 rubytter, oauth
  • XML/HTMLパーサー nokogiri
  • ユニットテスト test/unit


プログラムの拡張子は rb です。たとえば、hello.rb をテキストエディタで以下のように作成し、


printf "Hello World\n"



ruby hello.rb

で実行すると、


Hello World


と表示されます。"\n"は改行です。

たとえば、以下のようなプログラムが書けます。以下、ruby 1.93 で動作確認してあります。



数値演算ができます。


a = 1.5
b = 3
printf "%f\n", a*b

↓実行結果

4.500000


変数を宣言する必要はありません。値を代入したところで変数の型が決まります。浮動小数点数と整数を掛けると浮動小数点数になることは自動的に判断されます。

整数
http://doc.ruby-lang.org/ja/1.9.2/class/Fixnum.html
浮動小数点数
http://doc.ruby-lang.org/ja/1.9.2/class/Float.html



文字列が扱えます。


s = "good " + "morning."
printf "[%s]\n", s
printf "[%s]\n", s[0,4]
printf "[%20s]\n", s.upcase
printf "[%-20s]\n", s.capitalize
printf "[%-20s]\n", s.gsub(/morning/,'night')

printf "%d\n", "12".to_i + 3
printf "%d\n", "ffff".to_i(16)
printf "%d\n", 0xa0

実行結果

[good morning.]
[good]
[ GOOD MORNING.]
[Good morning. ]
[good night. ]
15
65535
160


文字列は 足し算記号で、連結できます。

文字列
http://doc.ruby-lang.org/ja/1.9.2/class/String.html



文字列を数式とみなして計算することができます。


formula = "a = 2; b = a * 3"
c = eval(formula)
printf "%d\n", c

↓ 実行結果

6


複数の文は、セミコロンでつなげます。最後に評価した式の値が、結果として得られます。

Kernel.#eval
http://doc.ruby-lang.org/ja/1.9.2/method/Kernel/m/eval.html



行列演算ができます。


a = Matrix[[11,12],[21,22]]
printf "%s\n", a+a
printf "%s\n", a*3
printf "%s\n", a*a
printf "%s\n", a.transpose
printf "%d %d %d %d\n", a[0,0], a[0,1], a[1,0], a[1,1]

↓実行結果

Matrix[[22, 24], [42, 44]]
Matrix[[33, 36], [63, 66]]
Matrix[[373, 396], [693, 736]]
Matrix[[11, 21], [12, 22]]
11 12 21 22


Matrix
http://doc.ruby-lang.org/ja/1.9.2/class/Matrix.html



時刻が扱えます。


# coding: shift_jis

now = "今は " + Time.now.strftime("%Y/%m/%d %H:%M:%S") + " です"
print "Hello world #{now}\n"

↓実行結果

Hello world 今は 2011/12/09 11:39:45 です


プログラム中やプログラム自身が日本語を扱う時は、1行目に文字コードを明記しておきます。

Time
http://doc.ruby-lang.org/ja/1.9.2/class/Time.html



正規表現が使えます。正規表現というのは文字列をパターンマッチングさせる手段です。


time = "2011/12/09 11:39:45"
/(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2})/ =~ time
year,month,day,hour,minute,second = $1,$2,$3,$4,$5,$6
printf "いまは #{year}年 #{month}月 #{day}日 #{hour}時 #{minute}分 #{second}秒 です。\n"

↓実行結果

いまは 2011年 12月 09日 11時 39分 45秒 です。


正規表現
http://doc.ruby-lang.org/ja/1.9.2/doc/spec=2fregexp.html



配列が使えます。


array = Array.new
array << "matsumoto"
array << "shiojiri"
array << "shiojiri"
array << "azumino"

i = 0
printf "%d %s\n", i, array[i]
i += 1
printf "%d %s\n", i, array[i]

array.sort.uniq.each { |city|
printf "[%s]\n", city
}

↓実行結果

0 matsumoto
1 shiojiri
[azumino]
[matsumoto]
[shiojiri]


配列に4つの文字列を追加し、それをソートし、重複を取り除き、それぞれの要素をprintfしています。

配列
http://doc.ruby-lang.org/ja/1.9.2/class/Array.html



ハッシュが使えます。変数名=値 の関係にあるものをたくさん覚えておくのに便利です。


hash = Hash.new
hash['username'] = "shima"
hash['password'] = "foo"
hash['password'] = "baa"
printf "%s\n", hash['username']
printf "%s\n", hash['password']
hash.keys.each { |key|
printf "'%s' => '%s'\n", key, hash[key]
}

↓実行結果

shima
baa
'username' => 'shima'
'password' => 'baa'


ハッシュ
http://doc.ruby-lang.org/ja/1.9.2/class/Hash.html



ファイルを書いたり読んだりできます。


array = [ "Tokyo", 0 ]
city1, time_diff1 = array
line = sprintf("%s %d", city1, time_diff1 + 9)
printf "%s\n", line

file_name = "test.csv"
File.open(file_name, 'w') { |f|
f.puts line
}

File.open(file_name, 'r') {|f|
city2, time_diff2 = f.gets
printf("%s %s\n",city2, time_diff2)
}

↓実行結果

Tokyo 9
Tokyo 9


配列には文字列や整数など異なる型の値を混ぜて入れることができます。
openという関数に、'{' で始まって '}' で終わる関数(これをブロックといいます)を渡して実行しています。'}' が実行されるときに、ファイルのクローズが自動的に行われます。

File
http://doc.ruby-lang.org/ja/1.9.2/class/File.html

sprintfフォーマット
http://doc.ruby-lang.org/ja/1.9.2/doc/print_format.html



Excel xlsファイルを読むことができます。

[Ruby] xlsファイルを直接読む
http://saltheads.blog134.fc2.com/blog-entry-61.html



関数を定義して、それを呼び出すことができます。


def average(x,y)
return (x+y)/2
end

n = average(10,20)
printf "%d\n",n

a = average(10.0,20.0)
printf "%f\n",a

実行結果
15
15.000000

この関数の書き方の場合、呼び出し側で整数を与えると整数の答えが、浮動小数点を与えると浮動小数点の答えが返ってきます。関数の引数や戻り値の型が実行時に決まる例です。

直交座標から極座標へ、極座標から直交座標へ変換する関数。

# polar coordinates 極座標へ
def to_polar(x,y)
return Math.sqrt(x*x + y*y), Math.atan2(y,x)
end

# rectangular coordinates 直交座標へ
def to_rect(r,th)
return r * Math.cos(th), r * Math.sin(th)
end

[[1.0, 1.0],
[-1.0, -1.0]].each { |x,y|
r,th = to_polar(x,y)
printf "x=%f y=%f -> r=%f th=%f\n",x,y,r,th
x, y = to_rect(r,th)
printf "r=%f th=%f -> x=%f y=%f\n\n",r,th,x,y
}

↓実行結果

x=1.000000 y=1.000000 -> r=1.414214 th=0.785398
r=1.414214 th=0.785398 -> x=1.000000 y=1.000000

x=-1.000000 y=-1.000000 -> r=1.414214 th=-2.356194
r=1.414214 th=-2.356194 -> x=-1.000000 y=-1.000000


多重代入といって、イコールの左側には2つ以上の変数を書くことができます。関数からは一度に複数の値を返すことができます。

多重代入
http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2foperator.html#multiassign




HTTPクライアントを書くことができます。


# coding: shift_jis

require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = "Windows IE 7"
agent.set_proxy('10.0.10.10', 8080) if false
agent.get('http://weather.yahoo.co.jp/weather/jp/20/4820.html')
html = agent.page
printf "%s\n", html.title
html.search('table').each { |table_tag|
cls = table_tag.attributes["class"]
if cls != nil && cls.value == "yjw_table" then
printf "%s\n", table_tag.search('table')[0].inner_text.gsub(/\s+/,"")
break
end
}

↓実行結果 (当然ながら、実行する日によって天気は違います)

中部(松本)の天気 - Yahoo!天気・災害
12月10日(土)曇り


Yahoo天気のサイトから、HTMLを取得し、その中にある今日の天気部分を抽出しています。Mechanizeを使ってWebサイトへの入力,巡回を自動運転させたりできます。

Mechanize
http://mechanize.rubyforge.org/



時刻とファイルが扱えるのでログファイルを作って、実行時間を順に記録することもできます。


now = Time.now.strftime("%Y/%m/%d %H:%M:%S")
File.open("./log.txt","a") { | file |
file.puts("#{now}\n")
}

2回実行したあとのlog.txtファイルの中身
2011/12/10 23:26:28
2011/12/10 23:26:29


Rubyのインタプリタを起動して、1行ずつ確かめながら実行させることができます。


D:\>irb
irb(main):001:0> a = 1.5
=> 1.5
irb(main):002:0> b = 3
=> 3
irb(main):003:0> printf "%f\n", a*b
4.500000
=> nil
irb(main):004:0> print a.class
Float=> nil
irb(main):005:0> print b.class
Fixnum=> nil


irbは、インタラクティブRubyの略です。

irb
http://doc.ruby-lang.org/ja/1.9.2/library/irb.html




最後にひとことアドバイス

  • 凝りすぎない。
    結果が出たらそれでよし。あまり時間をかけて凝ったプログラムにしないのがおすすめです。

  • 読みやすく書きましょう
    短く書くこともできますが、読みやすく書いたほうが、あとあと自分が他人が助かります。

  • Excelでやったほうがいい仕事もあります。
    なんでもrubyでやるより実はいいかも。のちほど、グラフを描いたり、きれいな帳票を作りたいなら、最初からExcelのほうがいいかも。

  • ネットワークに迷惑をかけない
    ネットワークにアクセスするプログラムは十分な注意が必要です。ネットワークに負荷をかけないようにする配慮が必要です。

  • いいプログラムができたら、人にも使ってもらいましょう。
    私のブログで紹介させてください。

  • ソースコードを読んでみましょう
    Rubyをインストールすると、ソースコードもインストールされます(libディレクトリなど)。ぜひ読んでみましょう。ここに紹介したライブラリも読み応えがあります。マルチスレッド、例外処理、イテレータ・クロージャ、Mixin、演算子オーバーロード、メタプログラミングなど数多くの技術が盛り込まれています。とても勉強になります。




参考文献

  • 入門用に何か1冊買うなら、
    Rubyレシピブック 第3版 303の技
    http://www.amazon.co.jp/dp/4797359986/
    ふだん使いには、これ1冊で十分です。私も愛用中。

  • 上級者、研究者用には、
    メタプログラミングRuby
    http://www.amazon.co.jp/dp/4048687158/
    かなり難解ですが、Rubyの裏側が勉強できます。目からうろこ落ち多数。



  • 「仕事で使うRuby」のプログラムを実行するのに必要十分な、

    Ruby 1.93 のインストール方法
    http://saltheads.blog134.fc2.com/blog-entry-63.html



    追記

    1ページ分ぐらいの分量で、このくらいにやさしく書いてある記事を探したのですがなかなか見つからなくて、自分で書くことにしました。厳密にいえば、Rubyには関数がなくメソッドだとか、いろいろ間違っているところもあるんですが、それよりもわかりやすさを優先しました。それでも気になるかたはメッセージください。いちおう聞きますw。

    短いプログラムの中にいろいろな要素をもりこんで、気づきを増やしたり、調べるきっかけになるような、プログラムにしようとしています。ヒントもいただければ。

コメントの投稿

非公開コメント

プロフィール

島敏博

Shima Toshihiro 島敏博
信州アルプスハイランド在住。HaskellとElixirが好き。組み込みソフトウェアアーキテクト、C++プログラマ、山歩き、美術館巡り、和食食べ歩き、日本赤十字社救急法指導員、インデックス投資、クラシック音楽、SESSAME会員、状態マシン設計、モデル駆動開発、ソフトウェアプロダクトライン、Rubyist、実践ビジネス英語

■ ツイッター
http://twitter.com/saltheads
■ Facebook
http://www.facebook.com/saltheads
■ Qiita
http://qiita.com/saltheads

印刷する場合は、ブラウザの印刷メニューではなく、このページの上から3cmくらいの青いところにある、「印刷」を押してみてください。少しうまく印刷できます。まだ完全ではないのですが、これで勘弁してください。


カテゴリ
最新記事
月別アーカイブ
最新コメント
検索フォーム
リンク
sessame
RSSリンクの表示