プログラムは,人がやるには苦痛を伴う単調な作業を正確に素早く行ってくれます.機械的に測定した実験データなどは,決まった処理を繰り返し行わなければならないことがあります.このような処理が,プログラムは大変得意です. ここではRubyプログラムの便利さの一端を感じるため,「カンマで区切られた数値の,各行の平均値を取って出力する」という極簡単な処理を行ってみます. * プログラムの名前 [#i293bd44] 名前は結構重要です.できれば何をするか分かる名前を付けましょう.ここでつくるプログラムは,各行の平均値をとるので「rowAverage.rb」という名前にしておきます.プログラムはコマンドラインで rowAverage.rb infile $ rowAverage.rb infile とすれば実行できるようにします.「infile」というのは,入力データを含んだテキストファイル名を仮に表しています.実行時,実際のファイル名に置き換えてください. * データの流れ [#z90239dc] データ処理を行うので,まずどんなデータを入力して,どんなデータを出力するかをハッキリさせておきます.以下のような入出力を想定します. ** 入力データ [#w9fbe378] 287.5 ,287.8 ,287.5 201.0 ,200.7 ,201.0 155.6 ,155.9 ,155.9,155.7 135.1,134.7 ,134.7 124.5,124.2 117.1 ,117.8 ,117.5 111.5 ,111.5 ,111.5 ... 何かの測定値がカンマで区切られています.区切りの量はいつも同じとは限りません.しかも,カンマの前後に半角スペースがあったりなかったりします. ** 出力データ [#p7e3c99c] つぎのように,行の平均値のみを出力することにします. 287.60 200.90 155.77 134.83 124.35 117.47 111.50 ... * コーディング [#p0f04cd2] いくつかのステップに分けてプログラムを完成させて行きます.Rubyの慣習に倣い#=>という記述を付けています.#=>があった場合,その行を実行するとどんな値になるか,どのように表示されるかを#=>の後に示しています.以下の例ではほとんどwhile文中にあるので,最初の一回目の実行を示しています. ** ステップ1 [#i4ad32df] まず,コマンドとして動作し,入力ファイルを各行ごとに取得するようにします. #!/usr/bin/env ruby while line = gets line.chomp! p line # => "287.5 ,287.8 ,287.5 " end 1行目はRubyスクリプトのコマンドとして動作させるための命令です.環境変数PATHの中から最初に見つかったrubyコマンドを実行するので,rubyのパスが「/usr/bin/ruby」の場合でも「/usr/local/bin/ruby」の場合でも対応できるので,便利な書き方です. つづくwhile文で入力ファイルを行ごとに取得しています.getsは標準入力もしくは第一引数の内容を,文字列として一行ずつ得ることができます.ここではgetsの内容をlineに入れて,lineがnilになるまでwhileで繰り返しています.chomp!メソッドは,文字列末尾の改行文字を破壊的に削るものです.これは,思わぬ誤動作を防ぐためです. 上の書き方はRubyでフィルタ系のコマンドをつくる場合のイディオムのようなものですから,覚えておいて損はないでしょう. ** ステップ2 [#v8384dda] 各行をカンマで区切る,という動作を加えます.つぎのようにSTRING.split()メソッドを使います. #!/usr/bin/env ruby while line = gets line.chomp! p line.split(",") # => ["287.5 ", "287.8 ", "287.5 "] end lineにsplit(",")メソッドを使用することで,lineの内容をカンマで区切ったものを要素とする配列になります. ** ステップ3 [#q1ba9feb] 余分な空白も取り除くようにします.STRING.gsub()メソッドを使い,正規表現により空白をマッチさせて削ります. #!/usr/bin/env ruby while line = gets line.chomp! p line.gsub(/\s/, "").split(",") #=> ["287.5", "287.8", "287.5"] end ** ステップ4 [#ya2fbf1d] 配列をeach()メソッドに渡し,要素一つずつ取り出します. #!/usr/bin/env ruby while line = gets line.chomp! line.gsub(/\s/, "").split(",").each{|x| p x.to_f #=> 287.5 } end ブロックに渡されたxにSTRING.to_fメソッドを使って,文字列から浮動小数点数に変換しています. ** ステップ5 [#uc3f538c] 和をとって要素数で割る,という平均の操作を加えます. #!/usr/bin/env ruby while line = gets line.chomp! sum = 0.0; i = 0 line.gsub(/\s/, "").split(",").each{|x| sum += x.to_f i += 1 } printf("%.2f\r\n", sum/i) end これで完成です.sumとiは,それぞれ行ごとの和,行ごとの要素数を表す変数です.sum = 0.0; i = 0で初期化し,printfで出力しています.printf中の%.2fで小数点以下を2桁に揃えています.\r\nはWindowsの改行コードです.