Rubyの基本事項
詳細はRuby各版のマニュアルを参照してください。
基本的には1.8系統は使わないようにし、2.0系のRubyを使うようにしましょう。 どちらでも動くスクリプトにこだわるのは苦労の元です。
此処ではRubyでツールを作るにあたって知って置いた方が良い事を羅列します。
Rubyでの日本語対応スクリプトの基本スタイル
文字の取り扱いは1.8系から1.9系、2.0系への変化で一番問題の起きやすい部分です。 日本語を取り扱うスクリプトはどちらか決め打ちで作った方が楽でしょう。 2.0系はデフォルトがUTF8に成っていること意外は1.9系とほぼ互換性があるようです。
Ruby 1.8.7系・文字コード指定
1.8.7系ではプログラムの先頭行におまじないとして必ず次の4行を入れておくと良いでしょう。 文字コードの詳細については此処では述べません。
シフトJISの場合
#! ruby -Ks # -*- mode:ruby; coding:shift_jis -*- $KCODE='s' require 'jcode'
EUCの場合
#! ruby -Ke # -*- mode:ruby; coding:euc-jp -*- $KCODE='e' require 'jcode'
UTF-8の場合
#! ruby -Ku # -*- mode:ruby; coding:utf-8 -*- $KCODE='u' require 'jcode'
先頭の行の #! ruby -Ks はこのファイルがスクリプトファイルとして実行されたときの為のものです。 UNIXには #! というコマンドが有って後ろに渡された文字列をコマンドラインとして実行し、 この行以下を起動したプログラムの標準入力へ渡します。 #!の前に空白を入れないで下さい。
rubyはスクリプトファイルが指定されない時、標準入力からスクリプトを受け取るようになっているため、 2行目以後をスクリプトとして受け取って実行します。
元はこの為ですが、rubyはスクリプトファイルのこの行を特別に判断し、 デフォルトの文字コードを決定します。そうすることで以下のファイルの文字コードを 間違わずに処理できるようになります。
次の行の cording: の指定行はマジックコメントと呼ばれエディタやrubyに文字コードを 教える為のものです。最近はこのマジックコメントでの指定が使われています。
$KCODE の行は実行可能な行で、rubyに以後の文字コードを指定します。 1.9以後では、この書き方は廃止されました。 1.9以後では警告が出ますが、1.8系のrubyでも利用する場合は残しておくのが安全です。
jcode は日本語文字コード用の拡張機能をStringクラスに追加して各種手続きで日本語が使えるようにします。 jcodeも1.9以後では廃止されていて必要なくなっています。
これらの行はプログラム中でASCIIしか使わなければ必要ありません。 でも、スタイルとして必ず書くようにしておくことで気づき難い間違いを少なくすることができます。
Ruby 1.9系と2.x系・文字コード指定
エンコーディングの詳細は 第4回 Ruby M17N 事始め:文字コード編 、 第2回 Ruby M17N 事始め:入門編 に詳しく書いてあります。
"invalid multibyte char (utf-8)" が出るとき
ここで紹介している #! をshebangと呼びますが、これはファイルの先頭にある必要があります。#! の前に空白やtab等があるとshebangとして認識されず、 そのために文字コードの指定が認識されない事となります。 同時にマジックコメント部分も無視されます。 空白をあけず必ず先頭から書いて下さい。
Windowswでは標準的にWindows-31j(ほぼ シフトJIS)を使用しているため、 エディタで普通に書いたプログラムはWindows-31jと成っています。 文字コードの指定が無いとデフォルトがutf-8と成ったruby 2.0以降では プログラム内の日本語部分が "invalid multibyte char (utf-8)" と成ります。
以下の例では1行目の -E 起動オプションで外部のエンコーディングを 2行目のマジックコメントで内部のエンコーディングを指定しています。 '-E Windows-31j:utf-8'のように -E 外部:内部 と指定する事も可能です。
SHIFT_JISの場合
#! ruby -EShift_JIS # -*- mode:ruby; coding:shift_jis -*-
Windowsで使用する場合にはShift_JISと指定しないで、Windows-31Jと指定する。 エンコーディングとしてShift_JISと指定した場合、Windowsの使用しているWindows-31Jとは 微妙に異なり、思わぬエラーや誤動作を引き起こすことがあります。普段はあまり意識しないで 使用しているのですが、注意しましょう。
日本語Windowsで使用する場合には下記の様にWindows-31Jを使用しましょう。
#! ruby -EWindows-31J # -*- mode:ruby; coding:Windows-31J -*-
EUCの場合
#! ruby -EEUC-JP # -*- mode:ruby; coding:euc-jp -*-
UTF-8の場合
#! ruby -EUTF-8 # -*- mode:ruby; coding:utf-8 -*-
入出力はWindows-31j、プログラムはUTF-8の場合
入出力をopenする時にFile.open('filename','r:windows-31j'の様に指定しても良い。
#! ruby -EWindows-31j:UTF-8 # -*- mode:ruby; coding:utf-8 -*-
Ruby スクリプトファイル名と実行
rubyのプログラムは通常 'rb'という拡張子を付けます。
#! ruby -ESJIS # -*- mode:ruby; coding:shift_jis -*- print "Hello WORLD\n"
上記プログラムをhello.rbという名前で保存してください。
コマンドラインから実行するには以下の様に起動します。
ruby hello.rb
Ruby用のエディタや開発環境等も幾つか有りますが、 プログラムは単なるテキストファイルですので、エディタでプログラムを書き、 コマンドラインから実行することが可能です。
フォーマットを使用した出力にはC言語等と同様のprintf,sprintfが使用可能です。 また、rubyの式の値を文字列に埋め込む事が可能で、 #{} を使用します。 #{}の中には任意の式が書けますし、変数だけでも良いです。 実際には式の結果が to_s というメソッドで文字列に変換されて埋め込まれます。
abc = "ABC" print "abcの値 = #{abc}, 1+2 = #{1+2}\n"
Rubyでの 繰返はイテレータを良く使う
whileやforを使ってループを作るC言語風の繰返しも使えますが、 イテレータを使って数え上げるのがruby流です。
イテレータとは順に数え上げていく機能です。
rubyでは配列やハッシュでデータを表現し、 それを数え上げて結果出力するのが一般的です。 通常eachというメソッド(手続き)が定義されていて順に数え上げてくれます。
(1..10).each {|i| print i}
{ } や do ... end はブロックと呼ばれ、ブロックは引数を受け取ることができ、 それが縦棒で囲まれた変数に渡されます。引数は複数の場合もあります。
(1..10)は 1,2,3,...,10と1から10までの数値を表し、eachを付けると それを順に取り出してブロックの引数 i に入れて、 ブロック内の手続き(print i)を実施します。
{ |x| ...} は do |x| .... end の形式で書くこともできます。 実行する手続きが一行ですまない場合にはこちらを使うと良いでしょう。 上記の例は次のように成ります。
(1..10).each do |i| print i end
Rubyでの ファイルの読み書き
ファイルの取り扱いは次のような形で行ないます。
File.open(file_name,mode) do |file| ... end
ブロックの中で渡されたファイルオブジェクトを通して読書きします。 上記の形式で処理すると自動的にclose処理が行われるので間違いが起き難くなります。 mode部分に何も指定しないか'r'を指定すると読み込みでオープンされます。 'w'を指定すると書き込み用にオープンされます。
ファイルディスクリプタを作って処理することも可能ですが、 上記の方法を使う事をお勧めします。
fd = open(file_name,mode) ... fd.close
File.openの形式は下記とほぼ同等です。 終了時に確実にcloseが実施されます。
f = open(path, mode) begin ... ensure f.close end
Rubyで テキストファイルを一行づつ処理する
一行づつ読込みながら別ファイルに書込み処理する場合には次の様にします。
File.open(file_name,'r') do |file| file.each_line do |line| line.chomp! # 改行の削除 行ごとのの処理 end end
Rubyで テキストファイルを一度に読書き処理する
全体を一度に読込んで一気に処理してしまうことも可能です。 例えば最初にテキストファイルを書き込み、次にそのファイルを読んで 文字列'abc'を'xyz'に置き換えて別ファイルに書き込むという例は、次の様になります。
#! ruby -EWindows-31J # -*- mode:ruby; coding:Windows-31J -*- File.open('abc_file.txt','w'){|f| f << "abc\n123\nabc\n"} File.open('xyz_file.txt','w'){|f| f << File.open('abc_file.txt','r').read.gsub(/abc/,'xyz') }
最初のFile行で3行のテキストを書込んでいます。これは次の様に書く事も可能です。
File.open('abc_file.txt','w').write("abc\n123\nabc\n")
書込む文字列の部分は変数で指定することも可能ですので、 変数に書込む文字列を作り込んでから一気に書込めます。
ただし、この書き方だと、 この行が終わった後もファイルがフラッシュされていません。 (プログラムの終了時にはフラッシュされます。) ですから、例題のコードの'abc_file.txt'ファイルの書き込み部分でこの書き方をすると 書いて直ぐに、ファイルをopenして読み出している部分で、まだ書込みが終了していない ファイルを参照し中身が無い結果となります。
例題のようにブロックの中で処理すると、ブロックの終了時にcloseが実施され その時点で確実に書込みが終了します。 書込み処理を行なう時にはブロックで処理するように習慣付けたほうが良いでしょう。 プログラムの終了直前での書込みならどちらでも構いません。
2っ目のFile行は'xyz_file.txt'を書き込みでopenし、 そのブロックの中で'abc_file.txt'を読込みでopenしてからreadで一気に読んでいます。 readでファイルの中身全体が読み出され文字列として扱えるようになります。 その文字列に対して変換処理をgsubで実行し、その結果を書いています。 書込みは write でも良いですし、 << 演算子でも書けます。
Rubyのブロックでの例外処理の仕方
begin 処理.. [rescue [error_type,..] [=> evar] [then] 例外処理..].. [else 例外が起こらなかったときの処理..] [ensure 抜け出るときに必ず行われる処理..] end
処理の中での個別の例外処理を行わず、例外処理を別に分けて処理することができます。 また抜け出るときには必ず行う処理が定義できるのでFile.openなどの場合にはここでcloseされます。
Ruby フィルタ・プログラムの薦め
ruby等でちょこちょこっと書くプログラムでは、標準入力からデータを受け取り、 標準出力へ書き出す形に作っておく事が便利な場合が多くあります。 この様な形式のプログラムをフィルタプログラムと呼びます。
フィルタとして作っておくとコマンドのリダイレクションで 他のコマンドと組み合わせて利用できます。
またプログラムを作るまでも無く1行で目的を達成できる場合もあります。
ファイルの書き換え ruby -i.bak -pe "gsub('xxx','yyy')" file.txt grepの替わり(x または y を含む行の表示) ruby -ne "print if /x|y/" file.txt
インストール ← : 基本事項 : → GUI(Tcl/Tk)
お勧めのRuby開発環境
Trail4You 仮想マシンバザール : Ruby統合開発環境仮想マシン上にruby統合開発環境をインストールしてあります。 rvm, git もインストール済みで各種rubyを切替ながら試せます。