Ruby

機能 概要 正規表現 名前 予約語 別名 パターン 演算子 Mixin
基本型 コードブロック メソッド クラス モジュール アクセス制御
システムメソッド イテレータ ファイルの取込み eval system yield
変数と定数 スコープ 配列 事前定義変数 グローバル定数
例外 例外を発生 例外の処理 大域脱出
基本入出力 出力 入力
文字 メタ文字 エスケープ文字列 文字列変換 文字列マッチ
プログラム例 コマンド行解析 コマンド文字列 例外を発生 ソート
実行 コマンド行引数 デバッガ エラー対処法
公式
マニュアル
method 組み込みクラス
モジュール
例外クラス
組み込み関数 組み込み変数 組み込み定数 添付ライブラリ
その他 練習問題 FAQ リンク 参考書 練習問題の解


機能

概要

Ruby は1995年に作者であるまつもとひろゆきさんが公開した、オブジェクト指向言語でありインタープリタです。
c + perl + java + sh にさらに様々な強力な記述法が加わって利便性に富んでいます。

たいへん強力な言語であり、windows 上ではよいスクリプト言語がなかったので便利に利用しています。

言語の名前の由来は、perl より強力なオブジェクト指向をめざして、誕生石がパールのつぎのルビーにしたそうです。

Ruby の特長はブロック付きメソッド呼び出しで、コードブロックとよばれています。

ruby のプログラムをファイルに格納する場合は、拡張子として .rb を使います。
例題を実行している ruby のバージョンは、ruby 1.8.5 です。またサンプルは windows XP で動作確認しております。

簡単なサンプルを示します。

プログラム説明
F_OUT1 = 'data.in'

f = File.new(F_OUT1,"r")
f.each_line{|line| puts line}
data.in というファイルを読んで全行を出力するプログラム

data.in ファイルを読むためにオープンします。
each_line は1行ずつ読み込むメソッド、puts は line を出力するメソッドです。
each_line の {} はコードブロックで each_line のパラメータのようにメソッド呼び出しできます。
|line| はコードブロックの引数リストです。 puts は line を出力します




正規表現

正規表現は、文字列を指定したり照合するのに使う記法です。 ここでは概要のみ記述します。
詳細は正規表現を参照してください。

意      味
c 非メタ文字 c AA
\c 文字 c \* *
^ 文字列のはじめ ^[ABC] A,B,C
$ 文字列のおわり ^$ 空行
. 任意の文字 . 任意1文字
[c1c2...] c1c2...の中の任意の文字 [ABC] A,B,C
[^c1c2...] c1c2...の中にない任意の文字 [^ABC] D,E,F....
[c1-c2] c1 から c2 までの範囲の任意の文字 [0-9]* 10進数
[^c1-c2] c1 から c2 までの範囲にない任意の文字 [^A-Z]+ 大文字を含まない単語
r1|r2 r1 か r2 に適合する任意の文字列 (black|blue) black,blue
(r1)(r2) r1 が x に、 r2 が y に適合するような xy (black)(blue) blackblue
(r)* r に適合する文字列の 0 個以上の連結 (AB)*C C,ABC,ABABC,..
(r)+ r に適合する文字列の 1 個以上の連結 (AB)+C ABC,ABABC,..
(r)? r に適合する 0 または 1個の文字列 (AB)?C C,ABC
(r) r に適合する任意の文字列 (AB) AB

c = 文字
r = 正規表現文字列




名前

Ruby の名前は、定数、変数、メソッド、クラス、モジュールを識別するのに使います。 識別子に使う名前には次の規則があります。

  1. ローカル変数、メソッドの引数、メソッド名はすべて小文字またはアンダースコア (_) で始まらなければなりません。
  2. グローバル変数はドル記号 ($) で始まらなければなりません。
  3. インスタンス変数はアットマーク (@) で始まらなければなりません。
  4. クラス変数は2つのアットマーク (@@) で始まらなければなりません。
  5. クラス名、モジュール名、定数は、大文字で始まらなければなりません。

先頭文字の後ろには、文字、数字、アンダースコアを自由に組み合わせられます。 ただしアットマーク記号の直後に数字を続けることはできません。
次に例を示します。

変      数 定数または
クラス名
ローカル グローバルインスタンスクラス
name $debug @name @@total PI
file_name$BASE_DIR @base @@analizeBASE
string1 $_ @X @@N MyClass
_aaa $Global @_ @@x_pos MakeHtml
_123 $1 @a123 @@SIGNAL FILE_DELM




予約語

変数名やメソッド名に使えない名前があります。それは Ruby が使うためにすでに予約されている名前です。
次は予約語の一覧表です。

BEGIN END alias and begin
break case class def defined?
do else elsif end ensure
false for if in module
next nil not or redo
rescue retry return self super
then true undef unless when
while yield __FILE____LINE__

__FILE__:実行中のファイル名
__LINE__:実行中の行番号

別名

alias 式は、既存のメソッド、演算子、グローバル変数、正規表現後方参照を参照する新しい名前(別名)を作成します。
ローカル変数、インスタンス変数、クラス変数、定数の別名は作成できません。 alias の引数は識別子かシンボルです。

alias 式        alias 新しい名前 古い名前
メソッドの未定義化   undef メソッド名[,メソッド名] ....


alias plus +

未定義化とはそのメソッドを見えなくすることです。 未定義化されたメソッドを呼び出すと NameError 例外が発生します。

パターン

パターンは、アクションの実行を制御します。 すなわち、パターンに適合した場合、指定したコードを実行します。

パターン適合するもの
BEGIN BEGIN レコード入力前の処理
END END レコード入力終了後の後処理
/正規表現/ /Asia/ 正規表現を含む文字列に適合:Asia を含む場合
式 =~ /正規表現/ line =~/Asia/ 式が正規表現を含む時適合:line が Asia を含む場合
式 !~ /正規表現/ line !~/Asia/ 式が正規表現を含まない時適合:line が Asia を含まない場合
式 =~ (パターン && パターン) line =~ (/Asia/ && /Europe/) 式が Asia を含みかつ Europe を含む場合
式 =~ (パターン || パターン) line =~ (/Asia/ || /Europe/) 式が Asia か Europe を含む場合
式 !~ パターン line !~ /Asia/ Asia を含まない場合
式 =~ /(パターン)/ line =~ /(Asia|Europe)/ Asia か Europe を含む場合




演算子

式は演算子を用いて組み合わせられます。

Ruby の演算子を優先度順にまとめます。 メソッドの列に * がある演算子はメソッドとして実装されていますので、オーバーライドできます。

演算子の優先順位は、下にいくほど低いです。

演算子意味メソッド
[][]= 要素の参照、設定 *
** べき乗 *
! ~ + - 否定、補数、単項加算 (+@)、単項減算 (-@) *
* / % 乗算、除算、剰余 *
+ - 加算、減算 *
>> << 右シフト、左シフト *
& ビット単位の論理積 *
^ | ビット単位の排他論理和、論理和 *
<= < > >= 比較演算子 *
<=> == === != =~ != 等号とパターンマッチ:!= と !~ はメソッドとして定義できません *
&& 論理積
|| 論理和
.. ... 範囲(境界を含む、境界を含まない)
?: 3項の if-then-else
= %= ~= -= += |= &=
>>= <<= *= &&= ||=
代入
defined? シンボル定義のチェック
not 論理否定
or and 論理結合
if unless while until 式修飾子
begin end 文括弧

プログラム例と実行結果

puts "Ruby 独特のオペレータ"
puts "間隔としての範囲:==="
p (1..10) === 5
p (1..10) === 15
p (1..10) === 3.14159
p ('a'..'j') === 'c'
p ('a'..'j') === 'z'

puts "比較演算子:<=>:(X < Y,X == Y,X < Y)=[-1,0,1]"
X=1
Y=10
p (X <=> Y)
p (X <=> X)
p (Y <=> X)

Ruby 独特のオペレータ 間隔としての範囲:=== true false true true false 比較演算子:<=>:(X < Y,X == Y,X < Y)=[-1,0,1] -1 0 1

Mixin

モジュールは include メソッドを使用して他のモジュールやクラスの定義にインクルードできます。 この場合 include したモジュールの定数、クラス定義、インスタンスメソッドは、 定義クラスの無名のスーパークラスに入れられます。

class | module モジュール名
   include 式
end




Ruby の式と文は行末で終わります。ただし、式が不完全な場合は除きます。 同一行内に複数の式を書く場合はセミコロンで区切ります。
行末にバックスラッシュを置けば、次行に継続できます。
コメントは # ではじめます。

=bigin で始まる行と =end で始まる行の間は、ドキュメントとして無視されます。
ソースの先頭が "__END__" だけを含む行をみつけると、プログラムの終了とみなします。

Ruby のソースファイルには、BEGIN と END のブロックをおくことができます。
BEGIN ブロックは、プログラムを読み込むときに実行される初期化ルーチンを宣言します。
END ブロックは、プログラム終了時に実行される後始末ルーチンを宣言します。

文種 書式プログラム例説明
コメント # コメント # this is a comment コメントです
選択 if 条件式
  文
end
if (/[a-z]+/ =~ line)
  puts line
end
line にアルファベット小文字の文字列があればそれを出力
if 条件式 [then]
  文
elseif 条件式 [then]
  文
else
  文
end
if (/[a-z]+/ =~ line)
  puts line
else
  puts "NG"
end
line にアルファベット小文字の文字列があればそれを、
なければ NG を出力
unless 条件式 [then]
  文
else
  文
end
unless (/[a-z]+/ =~ line)
  puts line
else
  puts "NG"
end
line にアルファベット小文字の文字列がなければそれを、
あれば NG を出力
case 式
  when
   文
   :
  else
   文
end
case word
when 'Asia'
  puts 'Japan and Korea'
when 'Africa'
  puts 'Kenya and Zanbia'
end
word が Aisa なら "Japan and Korea"、
Africa なら "Kenya and Zanbia" を出力
ループ for 変数 in 範囲
   文
end
s_val  = 0;e_val  = 10
for i in s_val..e_val
   puts i
end
.. は両端を含む範囲です

0から10までを出力
s_val  = 0;e_val  = 10
for i in s_val...e_val
   puts i
end
... は終端を含まない範囲です

0から9までを出力
式 while 条件式
MAX_LOOP  = 5
i         = 0
while (i<MAX_LOOP)
   puts i 
   i += 1
end
i が MAX_LOOP より小さい間ループ

0から4までを出力
式 until 条件式
MAX_LOOP  = 5
i         = 0
until i>MAX_LOOP
   puts i
   i  += 1
end
条件が偽の間ループを繰り返す

i が MAX_LOOP より大きくなるまで

0から5までを出力
制御
移行
next
最も内側のループを繰り返す
break [式] break if (i >= MAX_LOOP) 最も内側のループから抜ける
redo
ループ条件を再チェックしたりフェッチせず今の繰り返しをやり直す
retry
最も内側のループを再度繰り返す
exit 式
式の値はシェルに返される
return 式
式の値が返される




基本型

Ruby の基本型は、数値文字列配列ハッシュ範囲シンボル正規表現の7つです。

数値

Ruby の整数は Fixnum または Bignum クラスのオブジェクトです。 整数は先頭の符号、基数指示子(8進は0、16進は 0x、バイナリは 0b)の後ろに、 その基数による数値リテラルが続きます。

小数点および指数付きの数値リテラルは Float オブジェクトに変換されます。

文字列

Ruby の文字列は String クラスのオブジェクトです。
シングルクォートで囲まれた文字列では、\\ がバックスラッシュに、\' がシングルクォートに解釈されるだけです。
ダブルクォートで囲まれた文字列では、次表のような置換がおこなわれます。

\a0x07:ベル \nnn8進数(n=0-7)
\b0x08:バックスペース \xnn16進数(n=0-9,a-f)
\e0x1b:エスケープ \cxコントロール文字
\f0x0c:改ページ \C-xコントロール文字
\n0x0a:改行 \M-xメタx
\r0x0d:キャリッジリターン\M-\C-xメタコントロールx
\s0x20:空白 \x8進数(n=1~7)
\t0x09:タブ #{expr}expr の値
\v0x0b:垂直タブ

str1 = "This is line #$.\n"
str2 = 'That\' right'

配列

Array クラスのリテラルは、コンマで区切られた一連のオブジェクトリファレンスをブラケット ([]) で囲んで作ります。 末尾のカンマは無視されます。

arr = ["fred", 10,3.14,"This is a string",'baeny("pebbles")',]

文字列配列は略記法 %w(スペースで区切られた字句を配列の要素とする)を使って作れます。

arr = %w(fred  10,3.14 This\ is\ a\ string baeny("pebbles"),)

ハッシュ

ハッシュはキーとその値を格納する領域です。 Hash のリテラルは、キーと値のペアをブレース ({}) で囲むことで作成します。

colors ={  "red"    => 0xf00,
           "green"  => 0x0f0,
           "blue"   => 0x00f}

範囲

式1..式2または式1...式2は、条件式以外の場所では Range オブジェクトを返します。
式1..式2は、両端を含みますが、式1...式2は、終端を含みません。

1..10                    [1,2,3,4,5,6,7,8,9,10]
'a'..'h'                 [a,b,c,d,e,f,g,h]
0...Array.length         [0,1,2,3,...,(Array.length-1)]

(1...10).to_a            [1,2,3,4,5,6,7,8,9]
('bar'..'bat').to_a      ["bar","bas","bat"]

シンボル

Ruby のシンボルは名前の内部表現です。ある名前のシンボルを作成するには、名前のまえにコロン (:) を付けます。

正規表現

正規表現リテラルは Regexp 型のオブジェクトです。

/パターン/
/パターン/オプション
Regexp.new('パターン'[,オプション])

正規表現オプション

オプション 説明
i マッチ時に大文字小文字を区別しません。 グローバル変数 $= が設定されている場合も同じです。
o 特定の正規表現リテラル内の #{...} による式展開を一番最初に世紀表現の評価が行われたとき一度だけ行います。 このオプションを指定しないと、リテラルが Regexp オブジェクトを生成するたびに式展開します。
m 通常 . は改行を除く全ての文字にマッチしますが、このオプションを指定すると改行にもマッチします。
x 複雑な正規表現は読みにくいことがあります。 このオプションを指定すると、正規表現中に空白、改行、コメントを挿入できます。




Ruby の式を構成する単一項は次のいずれかです。

  1. リテラル
    数値、文字列、配列、ハッシュ、範囲、シンボル、正規表現があります。
  2. シェルコマンド
    バッククォートで囲まれた文字列でホストのオペレーティングシステムで実行できるコマンド文字列です。
  3. 変数リファレンスと定数リファレンス
    変数や定数は名前で参照されます。
  4. メソッド呼び出し
式は演算子を組み合わせて構成できます。 代入式は1つ以上の左辺値と1つ以上の右辺値をとれます。

プログラム例と実行結果

a ,b ,c = 1 , "cat" ,[3,4,5]
printf("a=%d  b=%s  c[]=%d,%d,%d\n",a,b,c[0],c[1],c[2])
x,y = 11,22
printf("x=%d  y=%d\n",x,y)
x,y = y,x
printf("x=%d  y=%d\n",x,y)

a=1 b=cat c[]=3,4,5 x=11 y=22 x=22 y=11

文括弧

式は begin と end で囲むことでグループ化できます。 文括弧の値は、最後に実行された式の値です。

条件式

条件式は真または偽に評価されます。




コードブロック

コードブロックとは、ブレース ({}) または do...end のペアで囲まれた ruby の文および式の集まりです。
ブロックの先頭には、縦棒 (|) で囲んでパラメータを指定できます。
コードブロックは、メソッド呼び出しの直後にだけ書けます。
ブロックの開始は、メソッド呼び出しの終わりと同じ論理行になければなりません。

メソッド呼び出し do |a1,a2, ...|
end

メソッド呼び出し {|a1,a2, ...|
}

メソッド

メソッドは値を返す式の固まりのことです。
メソッドは def を使って定義します。メソッド名は小文字ではじまらなければなりません。

項目 書        式
定義 
def メソッド名 [(arg1 [=val1],....][,*vararg][,&blockarg])]
式の並び 
end メソッドの引数 メソッドの引数のデフォルト値を指定できます。呼び出し元から明示的にわたされなかった場合、デフォルト値が使われます。 メソッド定義には0個以上の通常の仮引数に加えて、オプションで配列引数およびブロック引数を指定できます。 各仮引数はコンマで区切ります。仮引数リストは括弧で囲めます。 arg1 = val1 デフォルト値つき引数 *bararg 可変長引数 &blockarg ブロックを Proc 化して受け取る引数

仮引数はローカル変数で、後ろに = に続けてデフォルト値を与える式をオプションで付けられます。

メソッドの戻り値は最後に実行された式の値です。 return 式は即座にメソッドを終了します。 return は引数なしで呼び出すと nil を返し、1つの引数だけで呼び出すとその値を返し、 2つ以上の引数を指定して呼び出すと、その引数のすでての値を含む配列を返します。

def max(m,n) {
   m > n ? m: n
}
参照 
メソッド名(引数列)
メソッドはレシーバ、メソッド名、実引数、および関連付けられたブロック(省略可)を指定して呼び出します。
ind = max(m,n)
引数の例
def map_with_index(list)
   result = []
   list.each_with_index{ |item,idx|
      value = yield [item,idx]
      result << value
   }
   return result
end

p map_with_index([1,2,3]){|item,idx|  item*idx}

実行結果 [0,2,6]

プログラム例と実行結果

メソッドの例を示します。
Mtd クラスの中に options,varargs,mixed の3つのメソッドが定義されています。

class Mtd
   def options(a=99,b=a+1)
      [ a,b ]
   end
   def varargs(a,*b)
      [ a,b ]
   end
   def mixed(a,b=99,*c)
      [ a,b,c ]
   end
end


obj = Mtd.new
ary1 = obj.options
ary2 = obj.options(1)
ary3 = obj.options(2,4)
printf("ary1 = [%d,%d]\n",ary1[0],ary1[1])
printf("ary2 = [%d,%d]\n",ary2[0],ary2[1])
printf("ary3 = [%d,%d]\n\n",ary3[0],ary3[1])

var1 = obj.varargs(1)
var2 = obj.varargs(1,2)
var3 = obj.varargs(1,2,3)
printf("var1 = [%d,[%d]]\n",var1[0],var1[1][0])
printf("var2 = [%d,[%d]]\n",var2[0],var2[1][0])
printf("var3 = [%d,[%d,%d]]\n\n",var3[0],var3[1][0],var3[1][1])

mix1 = obj.mixed(1)
mix2 = obj.mixed(1,2)
mix3 = obj.mixed(1,2,3)
mix4 = obj.mixed(1,2,3,4)
printf("mix1 = [%d,%d,[%d]]\n",mix1[0],mix1[1],mix1[2][0])
printf("mix2 = [%d,%d,[%d]]\n",mix2[0],mix2[1],mix2[2][0])
printf("mix3 = [%d,%d,[%d]]\n",mix3[0],mix3[1],mix3[2][0])
printf("mix4 = [%d,%d,[%d,%d]]\n\n",mix4[0],mix4[1],mix4[2][0],mix4[2][1])

[ 実行結果 ] ary1 = [99,100] ary2 = [1,2] ary3 = [2,4] var1 = [1,[0]] var2 = [1,[2]] var3 = [1,[2,3]] mix1 = [1,99,[0]] mix2 = [1,2,[0]] mix3 = [1,2,[3]] mix4 = [1,2,[3,4]]




クラス

クラスは次の形式で定義しますが、クラス名は大文字で始めなければなりません。
super_expr は、スーパークラスになる Class を指定します。 省略すると Object クラスが使われます。
クラスからオブジェクトを生成するには new メソッドを使います。

class クラス名 [ < supe_rexpr ]
   本体
end

class クラス名 << anObject
   本体
end

obj = クラス名.new [ ([args, ....]) ]

プログラム例

class Cls
   CLASS1 = "class_1"
   CLASS2 = "class_2"
   def Myclass1
      CLASS1
   end
   def Myclass2
      CLASS2
   end
end

puts "test of class\n"
obj = Cls.new
printf("Myclass1 =%s\n",obj.Myclass1)
printf("Myclass2 =%s\n",obj.Myclass2)

Myclass1 =class_1 Myclass2 =class_2

モジュール

モジュールとは基本的にインスタンス化できないクラスのことです。 モジュールにはクラスメソッドとインスタンスメソッドを含めることができます。 モジュールの定数にアクセスするときは、スコープ解決演算子 :: を使います。

module モジュール名 
   本体
end

すでに作成済みのクラスやモジュールを取り込む場合は、2つの方法があります。

load "filename.rb"
require "filename"

プログラム例と実行結果

module Mod
   CONST = 1
   def Mod.method1
      CONST+1
   end
end

printf("Mod::CONST =%d\n",Mod::CONST)
printf("Mod:method1=%d\n",Mod.method1)

Mod::CONST =1 Mod.method1=2

モジュールはクラスに似ていますが、以下の違いがあります。

属性 Mix-in 継承 インスタンス生成
クラス できないできますできます
モジュールできますできないできない

アクセス制御

モジュールまたはクラスの定数やメソッドについて、次の3つの保護レベルを定義しています。

public 誰でもアクセスできます
protected 定義元クラスおよびそのサブクラスのオブジェクトだけが呼び出せます
private 関数形式でのみ呼び出せます。
従って private メソッドは定義元のクラスおよび直接のサブクラスで同じオブジェクトに対してしか呼び出せません

private [シンボル,...]
protected [シンボル,...]
public [シンボル,...]

アクセス制御は、メソッド呼び出し時に有効になります。




イテレータ

繰り返しのループ構造には様々なメソッドや組み込み関数が用意されています。

times,upto,downto,step,loop などです。

プログラム例と実行結果

no = 10
print "times\n"
no.times do
   print "Ho! "
end

print "\n\nupto\n"
startp = 0
endp   = 9
startp.upto(endp) do |x|
   print x," "
end

print "\n\ndownto\n"
endp.downto(startp) do |x|
   print x," "
end

print "\n\nstep\n"
startp.step(endp,3)  {|x|   print x," "}

print "\n\nloop\n"
startp = 0
endp   = 9
loop  {
   print startp," "
   startp += 1
   break if (startp == endp)   
}

times Ho! Ho! Ho! Ho! Ho! Ho! Ho! Ho! Ho! Ho! upto 0 1 2 3 4 5 6 7 8 9 downto 9 8 7 6 5 4 3 2 1 0 step 0 3 6 9 loop 0 1 2 3 4 5 6 7 8




ファイルの取込み

クラスやモジュールライブラリを取り込むには2つの方法があります。

  1. load メソッドは実行するたびに指定されたソースファイルを読み込みます。
  2. require は一度しか読み込みませんが、実行文です。

load "filename.rb"
require "filename"

eval

eval は構文エラーのない ruby のソースコードを解析、実行します。

r = 0...5
eval("for i in r;p i;end")

実行結果 0 1 2 3 4

system

Kernel.system メソッドは、与えられたコマンドを子プロセスで実行します。 正常に実行されると true を、そうでなければ false を返します。 実行に失敗した場合はグローバル変数 $? にその終了コードが格納されます。

ruby_cmd = "netstat -v >a"
system(ruby_cmd)

実行結果 Active Connections Proto Local Address Foreign Address State TCP owl:1030 localhost:1031 ESTABLISHED TCP owl:1031 localhost:1030 ESTABLISHED TCP owl:1150 ptsb.trial.motive.com:http CLOSE_WAIT

yield

ブロックつきメソッドを定義する場合、メソッドに渡されたブロックを実行するために yield を使います。
コードブロックはメソッドの本体内で yield で呼び出されます。戻り値はブロック内で評価された最後の式の値です。

def fib(max)
   i,j=1,1
   while i<=max
      yield i
      i,j=j,i+j
   end
end

fib(2000)  {|f| print f, " " }

実行結果 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

変数と定数

Ruby の変数と定数はオブジェクトへのリファレンスを保持しています。 変数の型は、その変数によって参照されるオブジェクトが何を返すかによって定義されます。
Ruby の定数は、代入されたときに生成されます。値を変更しようとすると、警告がでます。 メソッド内で定数を定義することはできません。

変数と定数のスコープ

グローバル変数はプログラム中どこでも使えます。 初期化されていないグローバル変数を参照すると nil が返ります。

クラス変数は、クラスまたはモジュール本体内であればどこでも使えます。 クラス変数は、1つのクラスの全てのインスタンス間で共有され、 サブクラスによって継承されます。

インスタンス変数はクラス全体に定義されたインスタンスメソッド内で使用できます。 初期化されていないインスタンス変数を参照すると nil が返ります。 クラスの各インスタンスはそれぞれ自身のインスタンス変数を保持しています。 クラスメソッドからインスタンス変数を参照することはできません。

ローカル変数は、スコープは静的に決まるが、存在は動的に確立される。 ローカル変数は、実行時に値が代入されると動的に生成されます。 スコープ内のまだ生成されていないローカル変数を参照すると、NameError 例外が発生します。

メソッドのパラメータは、そのメソッドに局所化された変数とみなされます。

ブロックパラメータは、そのブロックが呼び出されるときに値が代入されます。




配列

文字列や数を格納するために1次元の配列が用意されています。 配列は値を入れるか、Array オブジェクトを生成して作ります。

配列は [] 演算子を使って参照します。 整数のインデックスで配列を参照すると、その位置にあるオブジェクトが返されます。 その位置に値がないときは nil が返ります。
配列を負のインデックスで参照すると、配列の終わりから数えた位置の値が返ります。

a1 = [3.14,"pie",99]

a2 = Array.new
a2 [0] = "aaaa"
a2 [1] = "bbbb"

puts a2[-1]    bbbb
puts a1[7]     nil

配列は1組の数字 [start,count] でも参照できます。

a = [1,3,5,7,9]

a[1,3]       [3,5,7]
a[3,1]       [7]
a[-3,2]      [5,7]

配列は範囲でも参照できます。 範囲は開始位置と終了位置を2つまたは3つのピリオドで区切って指定します。

a = [1,3,5,7,9]

a[1..3]       [3,5,7]
a[3..3]       [7]
a[-3..-1]     [5,7,9]

以下の構文は、 配列の異なる添え字1つ1つを順番に変数に設定しながら文を実行します。

a = [ "a" , "b" , "c" ]
a.each { |x| print x," -- "}

a -- b -- c --

配列を要素とする配列を使って多次元配列を実現します。

data = [["a","b","c"],
        ["d","e","f"],
        ["g","h","i"]]

Array クラスにあるメソッド(組み込み関数)を説明します。

メソッド機     能a=["a","b","c","d",nil,"e"] b=["1","2","3","4","5"]
at指定した番目の配列要素を返します a.at(3)→d
clear配列の全要素を削除します
compact配列から nil の要素を取り除き、新しい配列を返します a.compact→a,b,c,d,e
delete配列の要素から指定要素を削除します a.delete("c")→c
each配列の各要素についてブロックを実行します
empty?配列が空のとき true を返します a.empty?→false
first配列のはじめの要素を返す a.first→a
index指定したオブジェクトと等しいはじめの要素を返します a.index("a")→0
join配列の要素を指定した区切り文字を結合し文字列を返します a.join(",")→a,b,d,,e
last配列の最後の要素を返します a.last→e
length配列の要素数を返します a.length→5
nitems配列の nil でない要素数を返します a.nitems→4
pop配列の最後の要素を取り除いて、それを返します a.pop→e
push指定された引数を配列の最後に追加します a.push→a,b,d,nil,f
replace配列の内容を引数で置き換えますa.replace(b)→1,2,3,4,5
reverse配列を逆順にならべますa.reverse→5,4,3,2,1
reverse_each配列の各要素の逆順でブロックを実行します
rindex指定したオブジェクトと等しい最後の要素を返します a.rindex("3")→2
shift配列の先頭の要素を取り除き、それを返します a.shift→1
sort配列の要素をソートします a.sort→2,3,4,5
to_a配列を返します a.to_s→2,3,4,5
uniq配列から重複する要素を除いた新しい配列を返します a.uniq→2,3,4,5
unshift指定したオブジェクトを配列の先頭に追加します a.unshift("Z")→Z,2,3,4,5




事前定義変数

Ruby には、以下の事前定義変数があります。 これらの変数は、すべての文で利用でき、ユーザが値をかえることもできます。

カテゴリ名前 意      味
例外情報$! raise に渡される Exception オブジェクト Exception
$@ 最後の例外によって生成されたスタックバックトレース Array
パターン
マッチ
$& 最後に成功したパターンマッチにマッチした文字列 String
$+ 最後に成功したパターンマッチにマッチした最後のグループの内容 String
$` 最後に成功したパターンマッチにマッチした文字列より前の部分 String
$' 最後に成功したパターンマッチにマッチした文字列より後の部分 String
$= nil または false 以外の値に設定すると、全てのパターンマッチ、文字列比較、文字列ハッシュ値で大小文字を区別しない Object
$1〜$9 最後に成功したパターンマッチにマッチした一連のグループの内容 String
$~ 成功したパターンマッチの結果をカプセル化したオブジェクト。 MatchData
標準
オブジェクト
ARGF $< の別名 Object
ARGV $* の別名 Array
ENV プログラムの環境変数を含む擬似ハッシュオブジェクト Object
false FalseClass クラスの特殊インスタンス FalseClass
nil nil クラスの特殊インスタンス NilClass
self 現在のメソッドのレシーバオブジェクト Object
true TrueClass クラスの特殊インスタンス TrueClass

グローバル定数

Ruby には以下の定数が定義されています。

名前 意      味
DATA プログラムに __END__ があると、__END__ 以降の行を返すファイルオブジェクトとして初期化されます。 IO
FALSE false の別名 FalseClass
NIL nil の別名 NilClass
RUBY_PLATFORM プラットフォームを示す文字列 String
RUBY_VERSION インタプリタのバージョン String
STDERR 標準エラー出力。$stderr の初期値 IO
STDIN 標準入力。$stdin の初期値 IO
STDOUT 標準出力。$stdout の初期値 IO
TOPLEVEL_BINDING Ruby のトップレベルのバインディングを表す Binding オブジェクト Binding
TRUE [i,j...] の形の配列の添字に使う区切子 TrueClass




例外

Ruby の例外は Exception クラスおよびその子孫のオブジェクトです。

例外を発生

Kernel.raise メソッドは例外を発生させます。

raise
raise 文字列
raise クラス | オブジェクト [ ,文字列 [ スタックトレース] ]

1番目の形式は $! に格納されている例外を発生させます。
2番目の形式は、指定した文字列をメッセージとして、新しい RuntimeError を発生させます。
3番目の形式は、第一引数に対して exception メソッドを呼び出すことで例外オブジェクトを生成し、 その例外のメッセージとスタックトレースを第二、第三引数に設定します。

標準の例外階層
fatal
interrupt
NoMemoryError
SignalException
ScriptError LoadError
NameError
NotImplementError
SyntaxError
StandardError ArgumentError
FloatDomainError
IndexError
IOError EOFError
LocalJumpError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit

例外の処理

例外は begin/end ブロックの範囲で処理できます。
ブロックには複数の rescue 節を書くことができ、0個以上の引数を指定できます。 引数なしの rescue 節は StandardError が引数に指定されたものとみなされます。 rescue 節 retry 文を指定すると、最も内側の begin/end ブロックが先頭から再実行されます。

begin
   コード
[rescue [param,...][=> var] [then]
   エラー処理 ....,....]
[else
   例外が発生しなかったときの処理 ...]
[ensure
   必ず実行する処理 ....]
end

大域脱出

Kernel.catch メソッドは関連付けられたブロックを実行します。

catch ( aSymbol | aString ) do
   ブロック ....
end
Kernel.throw は通常の処理に割り込みます。 throw にあうと、指定されたシンボルまたは文字列を持つ catch ブロックを捜して、そのブロックの直後から実行します。 throw に合致した catch が見つからないと throw を呼び出したところで NameError 例外を発生させます。




基本入出力

入出力を処理するための基本クラスは IO で、特定の外部リソースの間の双方向チャネルです。 File や BasicSocket クラスでは、IO クラスをサブクラス化しています。
カーネルモジュールには、gets,open,print,printf,putc,puts,readline,test などの I/O 関連のメソッドが定義されています。

出力

書式つきの出力は、printf 文を使います。書式は c 言語のものと同じです。

意味
puts 文字列 文字列を出力する
printf(書式,式,...) 式を書式に従って出力する
fp = File.new(ファイル名)
fp.puts(文字列)
fp.close
書き出すファイルをオープンする
文字列をファイル名に書き出す
ファイルをクローズする
str = sprintf(書式,式,...) 書式に従って文字列を作る

プログラム例

inFile = File.open("testfile","r")
inFile.each{ |ch| putc ch }
inFile.close

inFile  = File.open("testfile","r")
outFile = File.open("outfile","w")
   while line = inFile.gets
      outFile.puts(line)
   end
inFile.close
outFile.close

入力

IO クラスには each,each_line,gets,readline,readlines などのメソッドが用意されています。

意味
gets 1 行読み込みその文字列を返します
each_line 1 行読み込みその文字列を返します
readline 1 行読み込みその文字列を返します
readlines(path[,rs]) path で指定されたファイルを全て読み込んで、その各行を要素とする配列を返します。
eof EOF になったら真を返します。
rewind ファイルポインタを先頭に移動します。

プログラム例

msg   = "test of IO methord : "
func1 = "gets"
func2 = "readline"
FNAME = "io.rb"
fp    =  File.new(FNAME,"r")
puts msg + func1
while true
   line = fp.gets
   if (line == nil)  
      break
   end
   p line
end

puts msg + func2
fp.rewind
while true
   if fp.eof 
      break
   end
   line = fp.readline()
   p line
end




文字

メタ文字

メタ文字は、正規表現を表すために使う文字のことです。

メタ文字意      味 適合文字列
\ エスケープ・シーケンスをあらわす \nnewline
^ 文字列のはじめをあらわす    [^a-z]bab,zb
$ 文字列のおわりをあらわす    AA[a-z]$AAb,AAa
. 任意の1文字をあらわす    [a-z].a1,e4
[ ] 文字クラス内の任意の1文字に適合する [a-z]a,b,c
| 選択をあらわす    (A|B)$A,B
( ) グループ化をあらわす    (AB)+CABC,ABABC,ABABABC,...
* ゼロ個以上の並びからなる任意の文字列をあらわす [a-z]*asas etc
+ 1 個以上の並びからなる任意の文字列をあらわす [a-z]+asas etc
- 文字の範囲をあらわす    [a-z]a,b,c
? 空か適合する任意の文字をあらわす  A?CC,AC




エスケープ文字列

メタ文字列は、文字列および正規表現の中で特別な意味をもちます。

エスケープ文字列意      味
\b バックスペース \b
\f フォームフィード \f
\n 改行 \n
\r 復帰 \r
\t タブ \t
\ddd 8進数 ddd(ただし ddd は 0 から 7 までの3桁の数字) \127
\c 任意の文字 c そのもの。\\ は \ を表す \\

文字列変換

文字列を数値に、数値を文字列に変換する方法を示します。
str_val = "100" int_val = 200

出力
p str_val.to_i 100
p int_val 200
p str_val "100"
p int_val.to_s "200"

プログラム例と実行結果

str_val  = "100"
num_val  = "256".to_i

p "convert from string to number ------"
p str_val.to_i
p str_val.to_f
p str_val.hex
p str_val.oct
p str_val.to_i(2)

p "convert from number to string ======"
p num_val.to_s
p num_val.to_s(2)
p num_val.to_s(8)
p num_val.to_s(16)
実行
convert from string to number ------
100
100.0
256
64
4
convert from number to string ======
"256"
"100000000"
"400"
"100"

文字列マッチ

文字列の照会はパターンマッチを利用します。

プログラム例と実行結果

line = "Sun Feb 27 04:00:53 2005"

if line =~ /^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]+) ([0-9:]+) ([0-9]+)$/)
   printf("$1=%s  $2=%s  $3=%s  $4=%s  $5=%s\n",$1,$2,$3,$4,$5)
end
実行
$1=Sun  $2=Feb  $3=27  $4=04:00:53  $5=2005




プログラム例

コマンド行解析

GetOptLong クラスは、 GNU 形式のコマンド行オプション解析機能を提供します。

class Opt
   def ana_opt(opt,arg)
      case opt
      when $OP_STRING
         $match_str  = arg
      when $OP_DIRECT
         $dir_str    = arg
      when $OP_FILENM
         $fil_name   = arg
      when $OP_EXTENT
         $ext_str    = arg
      when $OP_HELP
         $help = 1
         printf($USAGE)
         exit 0
      end
      if $match_str == nil
         raise ArgumentError,"You must spcify match_string"
      end
   end
end

require 'getoptlong'
$USAGE    =" Usage : opt -s SERACH_STRING -d DIRRECTORY -e FILE_EXTENSION"
$OP_STRING="--string"
$OP_DIRECT="--dir"
$OP_EXTENT="--ext"
$OP_FILENM="--file"
$OP_HELP  ="--help"

opts = GetoptLong.new(
[ $OP_STRING   ,"-s",   GetoptLong::REQUIRED_ARGUMENT],
[ $OP_DIRECT   ,"-d",   GetoptLong::OPTIONAL_ARGUMENT],
[ $OP_EXTENT   ,"-e",   GetoptLong::OPTIONAL_ARGUMENT],
[ $OP_HELP     ,"-h",   GetoptLong::NO_ARGUMENT])

g = Opt.new
opts.each  {|opt,arg| g.ana_opt(opt,arg) }
printf("str=%s  dir=%s  ext=%s  help=%d\n",$match_str,$dir_str,$ext_str,$help)
実行

> opt -h
 Usage : opt -s SERACH_STRING -d DIRRECTORY -e FILE_EXTENSION 
> opt -s sss -e eee -d ddd
str=sss  dir=ddd  ext=eee  help=0

コマンド文字列

コマンド文字列を生成して、それを実行します。

ERR_USAGE = "処理年をいれてください   exp)  sys 2006"
DIR_UP    = ".."
DIR_DELM  = "\\"
DIR_BASE  = DIR_UP + DIR_DELM

if ARGV.length != 1
   puts ERR_USAGE
   exit
end

year     = ARGV[0]
ifile    = year + ".in"

perl_cmd = "perl check.pl   -f " + ifile
system(perl_cmd)
実行

>sys
処理年をいれてください   exp)  sys 2006

>sys 2006
I am the program of check.pl

例外を発生

例外を発生させます。

ERR_NO_ARG = "処理年をいれてください   exp)  excpt 2006"
ERR_VALUE  = "1900 より大きく 2100 より小さい値をいれてください"

if ARGV.length != 1
   raise ERR_NO_ARG
   exit
end

year     = ARGV[0].to_i
if year >= 1900 && year <= 2100
   puts year
else
   puts ERR_VALUE
   raise ArgumentError
end
実行

> excpt
C:/rub/text/excpt.rb:5: 処理年をいれてください   exp)  excpt 2006 (RuntimeError)

> excpt 2006
2006

> excpt 20
1900 より大きく 2100 より小さい値をいれてください
C:/rub/text/excpt.rb:14: ArgumentError (ArgumentError) 

ソート

以下のようなファイルの1カラム目をソートします。

have                 :  1
other                :  2
on                   :  1
symbols              :  1
context              :  1
oriented             :  1
words                :  1
The                  :  1
any                  :  1
In                   :  1
used                 :  1
optimized            :  1
           :
require "scanf"

FNAME    = "crs"
fp       = File.new(FNAME,"r")
h        = Hash.new

while true
   line = fp.gets
   if (line == nil)  
      break
   end
   ary = line.scanf("%s : %d")
   h.store(ary[0],ary[1])
end

h_ary = h.keys
h_sort= h_ary.sort

for i in 0...h.size
   key = h_sort[i]
   printf("     %-20s : %2d\n",key,h.fetch(key))
end




実行

Ruby プログラムの実行には、いろいろな方法があります。

  1. .rb のついたファイル名だけを入力する
  2. ruby [オプション] [--] プログラムファイル名 [引数]
    プログラムファイル名を指定しない、または - を指定すると、標準入力からプログラムソースを読み込みます。

プログラムファイル.rb
ruby [オプション] [--] プログラムファイル名 [引数]

[ 例 ] Ruby '$3==0 { print $1 }' file1 file2 Ruby -f pick.Ruby file1 file2

オプション

オプション意      味
-d $DEBUG を true に設定します Ruby -f arg.Ruby aaa bbb
-K Ruby が使用する漢字コードを指定します e=EUC,s=SJIS,u=UTF-8,a=ASCII Ruby -Ks jaa.rb
-n プログラムが "while gets;.....;end" で囲まれているように動作します Ruby -Ks jaa.rb




コマンド行引数

ruby プログラム名 引数列

ruby [-acdhlnpsSvwy] [-0 [oct]] [-Cdir] [-ecommand] [-Fpattern] [-i[ext]] [-Idirectory] [-Kcode]
[-rlib] [-T[level]] [-W[level]] [-x[dir]] [-yydebug] [--copyright] [--version] [--help] [file]

オプション説      明
-0数字 入力レコードセパレータ(`$/')を8進数で指定します。
-a 入`-n'や`-p'とともに用いて, オートスプリットモードをONにします。
-C directory スクリプト実行前に指定されたディレクトリに移動します。
-c スクリプトの内部形式へのコンパイルのみを行い, 実行しません。 コンパイル終了後, 文法エラーが無ければ, "Syntax OK"と出力します。
--copyright著作権表示をします。
-Kc Rubyの処理する漢字コードを指定します。
e,EEUC-JP
s,SShift JIS
u,UUTF-8
n,N指定なし
-d,--debug デバッグモードでスクリプトを実行します。$DEBUG を true にします。
-e script コマンドラインからスクリプトを指定します。
-Fregexp 入力フィールドセパレータ($;)に regexp をセットします。
-h,--help コマンドラインオプションの概要を表示します。
-i[extension] 引数で指定されたファイルの内容を置き換える(in-place edit)ことを指定します。
-I directory ファイルをロードするパスを指定(追加)します。
-l 行末の自動処理を行います。まず、$\ を $/ と同じ値に設定し, printでの出力時に改行を付加するようにします。 それから, -n フラグまたは-pフラグが指定されていると gets で読み込まれた各行の最後に対して String#chop!を行います。
-n プログラム全体を while gets() ~ end で囲んだように動作します。
-p プログラム全体を while gets() ~ print $_ end で囲んだように動作します。
-r feature スクリプト実行前に feature で指定されるライブラリを require します。
-s スクリプト名に続く, `-'で始まる引数を解釈して, 同名のグローバル変数に値を設定します。
-S スクリプト名が`/'で始まっていない場合, 環境変数 PATHの値を使ってスクリプトを探すことを指定します。
-T[level] 不純度チェックを行います。level を指定すると安全度レベルをそのレベルに設定します。 level 省略時は 1 を指定したのと同じです。 CGIプログラムなどでは-T1 程度を指定しておく方が良いでしょう。 $SAFE に指定したレベルがセットされます。
-v,--verbose 冗長モード。起動時にバージョンの表示を行い, 組み込み変数 $VERBOSEをtrueにセットします。 この変数がtrueである時, いくつかのメソッドは実行時に冗長なメッセージを出力します。
--version Rubyのバージョンを表示します。
-w バージョンの表示を行う事無く冗長モードになります。
-W[level] 冗長モードを三段階のレベルで指定します。それぞれ以下の通りです。
  1. -W0: 警告を出力しない
  2. -W1: 重要な警告のみ出力(デフォルト)
  3. -W2 or -W: すべての警告を出力する
-x[directory] メッセージ中のスクリプトを取り出して実行します。 スクリプトを読み込む時に、`#!'で始まり, "ruby"という文字列を含む行までを読み飛ばします。
-y,--yydebug コンパイラデバッグモード。

プログラムファイル名の後ろの引数列は大域配列 ARGV で参照できます。

プログラム例と実行結果

 例 : argtst.rb 
puts "ARGV=",ARGV
puts "ARGV.length=",ARGV.length

>ruby argtst.rb "aaa" "bbb" 1 2 3 ARGV= aaa bbb 1 2 3 ARGV.length= 5




デバッガ

デバッガを使うには -r debug を指定してインタプリターを起動します。

ruby -r debug [オプション] [ruby プログラム] [引数]

次はデバッガのコマンド一覧表です。

b[reak] [file:]line file 内の指定された行(省略時は現在行)にブレークポイントを設定する
b[reak] [file:]name file 内の指定された method にブレークポイントを設定する
b[reak] ブレークポイントとウォッチポイントを表示する
wat[ch] expr expr が真になったら中断する
del[ete] [nnn] ブレークポイント nnn (省略時は全ブレークポイント)を削除する
disp[lay] expr デバッガに制御が戻るたびに expr の値を表示する
disp[lay] 現在の式を表示する
undisp[lay] [nnn] ディスプレイ式を削除する(省略時は全て)
c[ont] 実行を継続する
s[tep] nnn=1 次の nnn 行を実行する。メソッドの中も実行する
n[ext] nnn=1 次の nnn 行を実行する。メソッドの中はスキップする
fi[nish] 現在の関数の出口まで実行する
q[uit] デバッガを終了する
w[here] 現在のスタックフレームを表示する
f[rame] 現在のスタックフレームを表示する
l[ist] [start-end] start から end までのソース行を表示する
up nnn=1 スタックフレームを nnn レベルまであげる
down nnn=1 スタックフレームを nnn レベルまでさげる
v[ar] g[lobal] グローバル変数を表示する
v[ar] l[ocal] ローカル変数を表示する
v[ar] i[nstance] objobj のインスタンス変数を表示する
v[ar] c[onst] Name name クラスまたはモジュールのインスタンス変数を表示する
m[ethod] i[nstance] obj obj のインスタンスメソッドを表示する
m[ethod] Name name クラスまたはモジュールのインスタンスメソッドを表示する
th[read] l[ist] すべてのスレッドを表示する
th[read] [c[ur[rent]]] 現在のスレッドの状態を表示する
th[read] [c[ur[rent]]] nnn スレッド nnn を現在のスレッドにして、実行を停止する
th[read] resume nnn スレッド nnn の実行を再開する
[p] expr 現在のコンテキストで expr を評価する。 expr には変数への代入やメソッドの呼び出しがふくまれていてもかまわない
empty ヌルコマンドは最後に実行されたコマンドを繰り返す




エラー対処法

現象 理由 対処
c の i++ という書き方はありません。このようにかくとエラーの内容からはわかりにくいです。 ruby にはこの記法はない i += 1




その他

練習問題

  1. 指定のファイルを行番号付で出力しなさい
    データ:no.rb プログラム名:no.rb

    FNAME = "no.rb"
    fp    =  File.new(FNAME,"r")
    lno   = 0
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       lno += 1
       printf("%5d %s",lno, line)
    end
     ===> 
       1 FNAME = "no.rb"
       2 fp    =  File.new(FNAME,"r")
       3 lno   = 0
       4 while true
       5    line = fp.gets
       6    if (line == nil)  
       7      break
       8    end
       9    lno += 1
      10    printf("%5d %s",lno, line)
      11 end
    

  2. 行番号付のレコードの行番号をはずしなさい。上記の逆です。
    プログラム名:rm_no.rb

  3. oracle の alert ファイルは以下のように日付が途中にあってわかりずらいので、 次にように先頭につけて remake しましょう。
    プログラム名:alert.rb

    alter database open
    Sun Feb 27 04:00:53 2005
    Thread 1 opened at log sequence 1437
      Current log# 3 seq# 1437 mem# 0: /oracle/oradata/SA04/dbs/log3SA04.dbf
    Successful open of redo thread 1.
    Sun Feb 27 04:00:53 2005
    SMON: enabling cache recovery
    SMON: enabling tx recovery
    Sun Feb 27 04:00:54 2005
    Completed: alter database open
    Shutting down instance (normal)
    License high water mark = 1
    Sun Feb 27 04:01:14 2005
    ALTER DATABASE CLOSE NORMAL
    Sun Feb 27 04:01:14 2005
    SMON: disabling tx recovery
    SMON: disabling cache recovery
     ===> 
    alter database open
    02/27 04:00:53] Sun Feb 27 04:00:53 2005
    02/27 04:00:53] Thread 1 opened at log sequence 1437
    02/27 04:00:53]  Current log# 3 seq# 1437 mem# 0: /oracle/oradata/SA04/dbs/log3SA04.dbf
    02/27 04:00:53] Successful open of redo thread 1.
    02/27 04:00:53] Sun Feb 27 04:00:53 2005
    02/27 04:00:53] SMON: enabling cache recovery
    02/27 04:00:53] SMON: enabling tx recovery
    02/27 04:00:54] Sun Feb 27 04:00:54 2005
    02/27 04:00:54] Completed: alter database open
    02/27 04:00:54] Shutting down instance (normal)
    02/27 04:00:54] License high water mark = 1
    02/27 04:01:14] Sun Feb 27 04:01:14 2005
    02/27 04:01:14] ALTER DATABASE CLOSE NORMAL
    02/27 04:01:14] Sun Feb 27 04:01:14 2005
    02/27 04:01:14] SMON: disabling tx recovery
    02/27 04:01:14] SMON: disabling cache recovery
    

  4. 英語の文章があります。各単語が何回出てくるか印刷しましょう。
    - , . () " などで囲まれた単語のそれらを無視します。
    データ:crossref.data プログラム名:crossref.rb

    Text editors are applications which are used strictly for editing and
    transforming text. In this context, "text" means a document which
    contains any arbitrary combination of characters, including letters,
    numbers, punctuation marks, and other symbols. Some examples include
    PostScript text files, BinHex or uuencoded data files, program source
    code files, or documents such as this one. The functional emphasis for
    a text editor is on manipulation of characters and lines (often within
    very large files), rather than words or other units of written
    language. This of course does not imply that text editors cannot or
    should not have word-oriented functions as well, but rather that they
    must handle a variety of arbitrary types of file content which word
    processors are not optimized for.
     ===> 
         BinHex               :  1     In                   :  1
         PostScript           :  1     Some                 :  1
         Text                 :  1     The                  :  1
         This                 :  1     a                    :  3
         and                  :  3     any                  :  1
         applications         :  1     arbitrary            :  2
         are                  :  3     as                   :  2
         but                  :  1     cannot               :  1
         characters           :  2     code                 :  1
         combination          :  1     contains             :  1
         content              :  1     context              :  1
         course               :  1     data                 :  1
         document             :  1     documents            :  1
         does                 :  1     editing              :  1
         editor               :  1     editors              :  2
         emphasis             :  1     examples             :  1
         file                 :  1     files                :  4
         for                  :  3     functional           :  1
         functions            :  1     handle               :  1
         have                 :  1     imply                :  1
         include              :  1     including            :  1
         is                   :  1     language             :  1
         large                :  1     letters              :  1
         lines                :  1     manipulation         :  1
         marks                :  1     means                :  1
         must                 :  1     not                  :  3
         numbers              :  1     of                   :  6
         often                :  1     on                   :  1
         one                  :  1     optimized            :  1
         or                   :  4     oriented             :  1
         other                :  2     processors           :  1
         program              :  1     punctuation          :  1
         rather               :  2     should               :  1
         source               :  1     strictly             :  1
         such                 :  1     symbols              :  1
         text                 :  5     than                 :  1
         that                 :  2     they                 :  1
         this                 :  2     transforming         :  1
         types                :  1     units                :  1
         used                 :  1     uuencoded            :  1
         variety              :  1     very                 :  1
         well                 :  1     which                :  3
         within               :  1     word                 :  2
         words                :  1     written              :  1
    

  5. 次の表の縦横の総和と平均を求めましょう。
    データ:matrix.data プログラム名:matrix.rb

       28670   22483  1253978     623   1  18002  433526
       27610   22144  1156768     502   2  17559  312027
       26121   21032  1097266     448   3  16683  335951
       27495   21827  1175768     524   4  17365  332899
       28233   22446  1221040     533   5  17924  420386
       31811   25543  1439033     574   6  20241  382184
       31642   25059  1313149     583   7  20013  409582
       34176   26893  1484714     686   8  21490  456873
       33977   26792  1451724     677   9  21372  424977
       34191   26876  1504664     721  10  21461  457493
       35542   28111  1581898     719  11  22510  568686
       32122   25527  1416194     619  12  20317  438023
       32092   25512  1399793     578  13  20334  456054
       32752   25536  1493162     737  14  20484  489811
       32910   25937  1429445     651  15  20765  468834
       33871   27323  1447990     575  16  21658  380243
       36582   28973  1623478     737  17  23100  450918
       39572   30910  1732042     856  18  24861  598125
       36296   28674  1654706     742  19  22893  499566
       37426   29112  1655542     854  20  23465  559575
     ===> 
         28670      22483    1253978        623          1      18002     433526      1757283
         27610      22144    1156768        502          2      17559     312027      1536612
         26121      21032    1097266        448          3      16683     335951      1497504
         27495      21827    1175768        524          4      17365     332899      1575882
         28233      22446    1221040        533          5      17924     420386      1710567
         31811      25543    1439033        574          6      20241     382184      1899392
         31642      25059    1313149        583          7      20013     409582      1800035
         34176      26893    1484714        686          8      21490     456873      2024840
         33977      26792    1451724        677          9      21372     424977      1959528
         34191      26876    1504664        721         10      21461     457493      2045416
         35542      28111    1581898        719         11      22510     568686      2237477
         32122      25527    1416194        619         12      20317     438023      1932814
         32092      25512    1399793        578         13      20334     456054      1934376
         32752      25536    1493162        737         14      20484     489811      2062496
         32910      25937    1429445        651         15      20765     468834      1978557
         33871      27323    1447990        575         16      21658     380243      1911676
         36582      28973    1623478        737         17      23100     450918      2163805
         39572      30910    1732042        856         18      24861     598125      2426384
         36296      28674    1654706        742         19      22893     499566      2242896
         37426      29112    1655542        854         20      23465     559575      2305994
     ---------  ---------  ---------  ---------  ---------  ---------  ---------  ===========
        653091     516710   28532354      12939        210     412497    8875733     39003534
         32654      25835    1426617        646         10      20624     443786      1950176
    




FAQ

リンク

Ruby 公式サイト ここからバイナリやマニュアルをダウンロードできます。
Ruby リファレンス・マニュアル Ruby 1.8.5 のリファレンス・マニュアルを少し見やすくしました

参考書

題名 著者 出版社
プログラミング Rubyデビット・トーマス、アンドリュー・ハントピアソン・エデュケーション
Ruby レシピブック青木峰郎、後藤裕蔵、高橋征義ソフトバンク パブリッシング




練習問題の解

解は1つではありませんので、参考にしてください。

  1. 指定のファイルを行番号付で出力しなさい。

    FNAME = "no.rb"
    fp    =  File.new(FNAME,"r")
    lno   = 0
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       lno += 1
       printf("%5d %s",lno, line)
    end
    

  2. 行番号付のレコードの行番号をはずしなさい。上記の逆です。

    FNAME = "noadd.txt"
    fp    =  File.new(FNAME,"r")
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       data = line.gsub(/^[ ]*[0-9]+ /,"")
       printf("%s", data)
    end
    

  3. oracle の alert ファイルは以下のように日付が途中にあってわかりずらいので、次にように先頭につけて remake しましょう。

    class Alert
       def change_mon(mon_str)
          mon_ary = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
          for i in 0...mon_ary.length
             if (mon_str == mon_ary[i])  
                return i+1
             end
          end
       end
    end
    
    FNAME = "alert.log"
    fp    =  File.new(FNAME,"r")
    cur_time = ""
    al       = Alert.new
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       if (line =~ /(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]+) ([0-9:]+) ([0-9]+)/)
    #       printf("2=%s 3=%s 4=%s 5=%s %s",$2,$3,$4 ,$5,line)
           mon = al.change_mon($2)
           day  = $3
           time = $4
           year = $5
           cur_time = sprintf("%02d/%02d %s] ",mon,day,time)
       end
       printf("%s%s",cur_time, line)
    end
    

  4. 英語の文章があります。各単語が何回出てくるか印刷しましょう。

    FNAME = "crossref.data"
    fp    =  File.new(FNAME,"r")
    word_ary = Array.new
    h        = Hash.new
    
    # ハッシュの作成
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       line.chomp
       word_ary = line.split(/[ \[\]\.\(\)\t,"\/\n\r\-]/)
    #  printf("%d %s %s %s\n",word_ary.length,word_ary[0],word_ary[1],word_ary[2])
       for i in 0...word_ary.length
          key = word_ary[i]
          if (key != "")
             if (h.member?(key))
                val = h.fetch(key)
                h.store(key,val+1)
             else
                h.store(key,1)
             end
          end
       end
    end
    
    # ハッシュの印刷
    p h.size
    h_ary = h.keys
    h_sort= h_ary.sort
    for i in 0...h.size
       key = h_sort[i]
       printf("     %-20s : %2d",key,h.fetch(key))
       if ((i%2) != 0)
          printf("\n")
       end
    end
    

  5. 次の表の縦横の総和と平均を求めましょう。

    FNAME     = "matrix.data"
    fp        =  File.new(FNAME,"r")
    ttl_tate  = Array.new
    lno       = 0
    
    while true
       line = fp.gets
       if (line == nil)  
          break
       end
       lno += 1
       line.chomp
       yoko = 0
       word_ary = line.split(/[ \t\n]+/)
    #   printf("%d %s %s %s\n",word_ary.length,word_ary[0],word_ary[1],word_ary[2])
       column  = word_ary.length
       for i in 1...column
          val          = word_ary[i].to_i
          yoko        += val
          val1         = ttl_tate[i].to_i + val
          ttl_tate[i]  = val1.to_s
          printf("%10d ",val)
       end
       val1             = ttl_tate[column].to_i + yoko
       ttl_tate[column] = val1.to_s
       printf("%12d\n",yoko)
    end
    
    # 総計を出力
    for i in 1...column
       printf(" %9s ","---------")
    end
    printf(" %11s\n","===========")
    
    for i in 1...column
       printf("%10s ",ttl_tate[i])
    end
    printf("%12s\n",ttl_tate[column])
    # 平均を求めて出力
    for i in 1...column
       printf("%10s ",(ttl_tate[i].to_i/lno).to_s)
    end
    printf("%12s\n",(ttl_tate[column].to_i/lno).to_s)