Ruby をはじめるなら、この本からはじめるのをお勧めします。かなりわかりやすいです。わかりづらいだろうなという部分に関しては、ちゃんと詳しく説明がされているし、ちょっと気になるなということはコラムが別に用意されているという具合です。『Rubyプログラミング入門
』 より全然読みやすく理解しやすいです。
この本で Ruby の基本を抑えたら、あとはWeb上の Ruby リファレンスマニュアルで何とかなるのではないかと思います。
参考
Ruby 覚書 目次
- 基本文法
- 基本クラス
- コマンドライン
- 変数
- メソッド
- クラス
- モジュール
- 例外処理
- 数値クラス (Integer)
- 配列クラス (Array)
- 文字列クラス (String)
- ハッシュクラス (Hash)
- 正規表現クラス (Regexp)
- 入出力クラス (I/O)
- File クラスと Dir クラス
基本文法
「‘(シングルクウォート)」 で囲まれた文字列の中は、エスケープ 「\(バックスラッシュ)」 記法が使えない。
puts メソッドは、行の終わりに改行コードが付与される。
p メソッドは、オブジェクトの状態に合わせた表示を行う。
コメントの表記法には、「# (シャープ)」 と 「=begin」、「=end」 で囲む方法の2種類がある。
# if - else 構文
if 条件
処理
elsif 条件
処理
else
処理
end
# unless 構文
unless 条件
処理
end 条件
# while 構文
while 条件
処理
end
# times メソッド
繰り返し回数.times {
処理
}
# each メソッド
オブジェクト.each {|n|
処理
}
# case 構文
case 比較したいオブジェクト
when 値1
処理
when 値2
処理
when 値3
処理
else
処理
end
# if 構文 の変形版
print "a if a # for - in 構文
for 変数 in 開始値 .. 終了値
処理
end
# until 構文
until 条件
処理
end
# loop 構文 (ひたすらループを行う)
loop {
処理
}
- case 文の比較は ===
- case 文の条件比較には 「
===」 演算子が使われる。基本的には 「==」 と同じ意味だが、もう少しゆるい意味での一致を判断する。
- Range オブジェクト
-
for in構文には Range オブジェクトが使える。Rangeオブジェクトは開始値と終了値を持つオブジェクトである。「..」 と 「...」 の違いは、「..」 はarray[n]からarray[m]までを繰り返すのに対し、「...」 はarray[n]からarray[m-1]までを繰り返す点。「..」 が使えるところならどこでも 「...」 が使える。for in構文には、配列をとることもできる。
- 繰り返しの制御
- 繰り返し構文には、「
break(繰り返しを終了する)」、「next(次の条件で繰り返しを行う continue )」、「redo(同じ条件で繰り返しを行う)」 のキーワードが使える。
条件には、true / false / nil で判断できる条件を記述する。false と nil は 偽、それ以外は 真 として処理される。
- Tips
- 数値の 0 も真として判定される。
メソッド定義
def メソッド名(引数1, 引数2)
処理
end
他のライブラリを取り込みたいときは 「 require "ライブラリファイル名" 」 を使う。ライブラリファイル名には拡張子 「.rb」 は不要。
基本クラス
配列を生成するときには 「 [obj] 」 を使う。
ハッシュを生成するときは 「 {key => value} 」 を使う。
ハッシュオブジェクトにアクセスするときには 「 オブジェクト[key] 」 で行う。
配列のサイズを取得するには 「size 」 メソッドを使う。
ハッシュの each は、ブロック変数を2つとる
hash.each {|key, val|
処理
end
Ruby では、正規表現は、「 /パターン/ =~ "文字列" 」 のように、パターンを左側に置くのが慣習になっている。
パターンマッチングの結果は、数値で返される。マッチングしなかった場合は 「 nil 」 が返される。
コマンドライン
コマンドライン引数は 「 ARGV 」 で受け取る。これは配列オブジェクトである。
オープンしたファイルハンドルの 「 read 」 メソッドは、内容をテキストとして返す。一行ずつ取り出したいときは 「 gets 」 を使う。
ruby を起動する際に、「 -e ‘command’ 」 を指定すると、直接コマンドを実行する。
変数
表記法によって変数の意味が変わる。
| 種類 | 表記法 | 例 |
|---|---|---|
| ローカル変数 | 先頭がアルファベットの小文字か、「_ (アンダーバー)」で始まるもの | hoge, foo, _bar |
| グローバル変数 | 先頭が 「 $ 」 で始まるもの |
$global |
| インスタンス変数 | 先頭が 「 @ 」 で始まるもの |
@name, @age |
| クラス変数 | 先頭が 「 @@ 」 で始まるもの |
@@count |
| 定数 | 先頭がアルファベットの大文字で始まるもの | Parameter, RUBY_VERSION |
オブジェクトの同一性 (ID) を取得するには 「 id 」 メソッドを使う。ID で比較するには、「 equal? 」 メソッドを使う。値の比較を行うときは 「 == 」 演算子を使う。厳密な値の比較を行いたいときは 「 eql? 」 メソッドを使う。
- 変数の式展開
- 「 " " 」 で囲んだ文字列の中で変数を展開するには 「
#{ }」 を使う。
- Tips
- Ruby では、演算子もクラスのメソッドとして定義されている。そのため、演算子のオーバーライドが可能である。
組み込み変数
組み込み変数に関しては、Rubyリファレンスマニュアル (組み込み変数) を参照。
組み込み定数に関しては、Rubyリファレンスマニュアル (組み込み定数) を参照。
メソッド
Ruby では、真偽値を返すメソッドには 「 ? 」 を慣習としてつける。例: obj.equal?
破壊的メソッドには 「 ! 」 を慣習としてつける。 例: " 破壊的メソッド ".chomp!
- 破壊的メソッド
- メソッド名に 「
!」 がついたメソッドを破壊的メソッドと呼ぶ。このメソッドは、自分自身の状態を変更する。
引数をとらないメソッドは、「 () 」 をつけないのが慣習らしい。
メソッドの引数にはデフォルト値を設定することができる。「 引数名 = 値 」 と記述する。
メソッドの戻り値には 「 return 」 を使う。return を書かないときは、メソッドの最後に評価された値が戻り値になる。return の引数を省略すると nil を返すことになる。
メソッド引数に「*」をつけると、可変引数をまとめて配列として受け取ることが出来る。
可変引数の例
def print_all(*args)
p args
end
print_all(1, 2, 3, 4, 5) #=> [1, 2, 3, 4, 5]
組み込み関数
組み込み関数に関しては Rubyリファレンスマニュアル (組み込み関数) を参照。
クラス
インスタンスが何クラスのオブジェクトなのかを知るには 「 class 」 メソッドを使う。
インスタンスがクラスに属するかどうかを判定するには 「 instance_of? 」 メソッドを使う。
インスタンスがクラスに属するかどうかを、継承関係までさかのぼって判定するには 「 is_a? 」 メソッドを使う。
コンストラクタは 「 initialize 」 メソッド。
インスタンス変数のアクセサメソッドは、「 attr_reader :属性 」、「 attr_writer :属性 」、「 attr_accessor :属性 」 で定義する。
クラスの定数にアクセスするには 「 クラス名::定数 」 といった表記を使う。
アクセサメソッドの定義例
class クラス名
attr_accessor :name
attr_reader :age
def initialize(引数) # コンストラクタ
@name = "hamasyou"
@age = 23
end
end
クラスメソッドの定義方法
クラスメソッドの定義には3種類ある。「 def クラス名.メソッド名 end 」、「class << クラス名 def メソッド名 end end 」、「def self.メソッド名 end 」。
クラスメソッド定義方法
# 定義方法1
class クラス名
def クラス名.メソッド名
処理
end
end
# 定義方法2
class クラスB
end
class def メソッド名
処理
end
end
# 定義方法3
class クラス名
def self.メソッド名
処理
end
end
既存のクラスにメソッドを追加する
定義済みのクラスにメソッドを追加するには、同名のクラスを定義し、その中でメソッドを定義すればよい。
既存のクラスの拡張
class String
def len
return self.length
end
end
- self 変数
- メソッドの内部から自分自身を参照するには 「
self」 変数を使う。
クラスの継承
クラスの継承は 「 class サブクラス < スーパークラス end 」 で行う。
- super メソッド
- メソッドの内部から 「
super」 メソッドを呼び出すことで、スーパークラスの同名のメソッドを呼び出すことができる。
メソッドの公開修飾子
「 public (インスタンスメソッドとして公開) 」、「 protected (クラスの内部と同一クラス (サブクラスを含む) 内からレシーバ経由で呼び出せる) 」、「 private (クラス内部からのみ呼び出せる) 」。
公開修飾子の例
class クラス名
def パブリックメソッドA
処理
end
public :メソッドA
def プライベートメソッドA
処理
end
private :プライベートメソッドA
public # 引数を指定しない場合は、ここ以降が public になる
def パブリックメソッドB
処理
end
end
- レシーバとは
- 「
オブジェクト.メソッド(引数)」 の形式で呼び出されるオブジェクトのことを、レシーバと呼ぶ。メソッド呼び出しのメッセージを受け取るものという意味。
モジュール
モジュールは、クラスと違いインスタンス化することができない。モジュールは継承することができない。
モジュールは、名前空間を切る役割を持つ。「 モジュール名::メソッド名 」 といった形式でメソッドを呼び出すことになる。
「 include モジュール名 」 キーワードを使うと、モジュールを現在の名前空間に取り込むことができる。つまり、「 メソッド名 」で呼び出すことができるようになる。
Mix-in
モジュールをクラスに取り込むことを Mix-in と呼ぶ。クラス定義の中で 「 include 」 を行うことでクラスにモジュールで定義されているメソッドや定数を取り込むことができる。
モジュールの作成例
module モジュール名
def モジュールメソッドA
処理
end
# モジュールメソッドとして公開する
module_function :モジュールメソッドA
end
- module_function として公開しなければ使えない
- モジュールで定義したメソッドは、「
module_function」 キーワードを使って公開しなければ、「モジュール名::メソッド名」 の形で呼び出すことができない。「module_function」 がされていないメソッドは、同一モジュール内か、「include」 で取り込まれたときしか呼び出すことができない。
例外処理
例外処理構文
begin
# 例外が起きる可能性のある処理
rescue 例外クラスA => 変数
# 例外クラスAが起きたときの処理
rescue => 変数
# その他の例外が起きたときの処理
ensure
# 例外が起きる起きない関わらず
# 絶対に呼び出される処理
end
- 処理をやり直す
- 「
rescue」 で例外を捕捉した場合、「retry」 キーワードを使うことで 「begin」 から処理をやり直しすることができる。
例外を発生させる
「 raise メッセージ 」 か 「 raise 例外クラス [, メッセージ] 」 で例外を発生させることができる。
- rescue 節の中で raise すると
- rescue 節 の中で 「
raise」 を単独で呼び出すと、最後に発生した例外 ($!) を再スローすることができる。
- $! と $@
- 「
$!」 は最後に起こった例外を表す。「$@」 は例外が起こった場所に関する情報を表す。
catch と throw
Ruby における 「 catch と throw 」 は goto 文として使うことができる。「 catch 」 の引数に指定したシンボルが、catch 節中でスローされたら、catch 節を抜け出すことができます。
catch - throw の例
catch (:exit)
if a == 10
if b == 20
if c == 30
throw :exit, "catch の戻り値になる"
end
end
end
end
シンボルとは、Ruby が内部でメソッド名などの識別に使っている数値で、任意の文字列に対して異なった値が割り当てられます。メソッド名の先頭に 「:」 をつけることで、対応するシンボルオブジェクトを得ることができます。
数値クラス (Integer)
x.divmod(y)
x を y で割ったときの商とあまりを配列にして返す。
x.remainder(y)
x を y で割ったときの余りを返す。符号は、x の符号に一致する。
obj.to_xxx
obj を 別の型に変換する。
to_i は Integer 型、to_f は Float 型にそれぞれ変換する。
n.times {|i| ...}
n 回の繰り返しを行う。i には 0 .. n-1 の値が渡される。
from.upto(to) {|i| ...}
from から to に達するまで i を加算しながら繰り返す。
from.down(to) {|i| ...}
from から to に達するまで i を減算しながら繰り返す。
from.step(to, step) {|i| ...}
from から to に達するまで step を加算しながら繰り返す。
配列クラス (Array)
%w(あ か さ た な)
#=> ["あ", "か", "さ", "た", "な"]
"あ か さ た な".split()
#=> ["あ", "か", "さ", "た", "な"]
["あ", "か", "さ", "た", "な" ][1 .. 3]
#=> ["か", "さ", "た"]
["あ", "か", "さ", "た", "な" ][1 ... 3]
#=> ["か", "さ"]
["あ", "か", "さ", "た", "な" ][1, 3]
#=> ["か", "さ", "た"]
array.slice(n .. m)
array 配列の n 番目から m 番目 までの配列を返す。
array[n .. m] と同じ処理。
array.slice(n, len)
array 配列の n 番目から len 要素分 の配列を返す。
arrray[n, m] と同じ処理。
array.value_at(n1, n2, ...)
array 配列の n1 番要素 n2 番要素 ... を集めた配列を返す。
["あ", "か", "さ", "た", "な" ].value_at(0, 1, 3)
#=> ["あ", "さ", "な"]
array.unshift(obj)
配列の先頭に obj を追加する。
array.shift()
配列の先頭から要素を一つ取り出し返す。配列は詰められる。
array.push(obj)
obj を配列の末尾に追加する。
array.pop()
配列の末尾の要素を一つ取り出し返す。配列からはなくなる。
array.uniq()
array.uniq!()
配列中の重複する要素を削除した配列を返す。
array.collect {|item| ...}
array.collect! {|item| ...}
配列の各要素をブロックで評価した値と入れ替える。
要素の数は変わらない。
array.reverse()
array.reverse!()
配列の要素を逆順に並び替える。
array.sort()
array.sort!()
array.sort {|a, b| ...}
array.sort! {|a, b| ...}
配列の要素を並び替える。
並び替えの方法を指定する場合はブロックを伴う方を使う。
array.each {|item| ...}
array.each_with_index {|item, i| ...}
配列の要素をイテレーションする。
each_with_index は、配列のインデックスがブロックに渡される。
array.reject {|item| ...}
array.reject! {|item| ...}
要素を評価した結果が真になったものを除いた配列を作る。
文字列クラス (String)
「 " 」 で囲まれた文字列中で 「 #{ } 」 を使うと、変数を展開できる。
「 %Q、 %q 」 を使うと、「 " 」 と 「 ‘ 」 の代わりになる。「 %Q 」 が 「 " 」 の代わりで、「 %q 」 が 「 ’ 」 の代わりになる。
ヒアドキュメントも使える。
%Q, %q
%Q| 「" "」 や 「' '」の代わりに使える\n |
%q{ 区切り文字には何でも使えるみたい }
sprintf(format, arg, ...)
printf と同じ処理を行うが、画面表示ではなく、文字列を作る。
str.size
str.length
文字列のバイト数を返す。長さではないので注意すること。
str.chop
str.chop!
str.chomp
str.chomp!
chop は文字列の最後の一文字を切り捨てる。
chomp は文字列の最後に改行があれば切り捨てる。
str.index("abc")
str.rindex("abc")
文字列が最初に現れるインデックスを返す。
rindex は後ろから調べる。
str.include?("abc")
文字列が含まれているかどうかを返す。
str.sub(pattern, replace)
str.sub(pattern) {|matched| ...}
str.sub!(pattern, replace)
str.sub!(pattern) {|matched| ...}
str.gsub(pattern, replace)
str.gsub(pattern) {|matched| ...}
str.gsub!(pattern, replace)
str.gsub!(pattern) {|matched| ...}
sub は最初にパターンにマッチした部分を置き換える。
ブロックを伴う場合はブロックの戻り値で置き換える。
gsub はパターンにマッチした部分すべてを置き換える。
str.upcase
str.upcase!
str.downcase
str.downcase!
str.swapcase
str.swapcase!
str.capitalize
str.capitalize!
メソッドの名の通り。
- 日本語の文字列の長さを調べる
- 正規表現を使うと日本語も正しく文字数を調べられる。
- ‘オブジェクト指向スクリプト言語Ruby’.split(//e).length # 文字コードが EUC-JP の場合
- ‘オブジェクト指向スクリプト言語Ruby’.split(//s).length # 文字コードが Shift_JIS の場合
ハッシュクラス (Hash)
ハッシュを作るには 「 { } 」 を使う。「 key => value 」 の形で要素を作る。
hash.keys
hash.each_key {|key| ...}
キーを返す。
hash.values
hash.each_value {|value| ...}
値を返す。
hash.each {|key, value| ...}
キーと値をペアで返す。
hash.has_key?(key)
hash.has_value?(val)
has_key? はハッシュがキーを持っているかを判定する。
has_value? はハッシュが値を持っているかを判定する。
hash.size
ハッシュのキーの数を返す
正規表現クラス (Regexp)
パターンマッチングは、「 /pattern/ =~ 文字列 」 の形で行うことができる。マッチしたときは、その位置を返す。マッチしなければ 「 nil 」 を返す。
「 ^ や $ 」 は、行頭や行末にマッチする。ただし、「 "abc\nhoge" 」 のように、文字列の途中に改行がある場合に 「 ^ 」 を使うと abc と hoge にマッチすることになる。
文字列の先頭、末尾にマッチングさせたいときには 「 \A と \Z 」 を使う。\A は文字の先頭に、\Z は文字の末尾にそれぞれマッチする。
- %r の使い方
-
%r を使うと、パターン中で 「 / 」 を使いたいときに便利。例: 「
%r{this is a pattern} や %r|this is a pattern|」
正規表現の詳しい表記法に関しては Rubyリファレンスマニュアル (正規表現) を参考にすること。
入出力クラス (I/O)
標準入力(STDIN) と標準出力(STDOUT) は、バッファリングされる。標準エラー出力(STDERR) はバッファリングされずにすぐにフラッシュされる。
それぞれ、$stdin、$stdout、$stderr のグローバル変数か、STDIN、STDOUT、STDERR の組み込み定数で参照できる。
File.open(filename, "r|r+|w|w+|a|a+|b") {|f| ...}
ファイルを開く。ブロックを抜けるとファイルが閉じられる。
io.readlines
I/O オブジェクトの各行を配列にして返す。一気に読み出す。
io.each {|line| ...}
I/O オブジェクトをイテレーションする。
io.lineno
現在の読み込み行数を返す。
io.gets
io.puts
文字列の最後に改行コードをつけて読み込む / 書き込む。
io.getc
io.putc
文字列を1バイト読み込む / 書き込む。
io.printf(format, arg1, arg2)
フォーマットして I/O オブジェクトに出力する。
io.write(str)
文字列を書き込む。
io.flush
出力バッファをフラッシュする。
File クラスと Dir クラス
ファイルを表すのが 「 File 」 クラス。ディレクトリを表すのが 「 Dir 」 クラス。
- File クラスの拡張
- ファイルクラスに 「
copy や move」 といったメソッドを拡張するためには、「require "ftools"」 を行う。
- Find モジュール
- 「
require "find"」 で取り込まれるFindモジュールを使うと、ファイルの検索等ができるようになる。require "find" Fild::find(dir) {|path| ...}
- Tempfile クラス
- 「
require "tmpfile"」 で使えるようになるTempfileクラスは、テンポラリファイルを扱うクラス。newで作成したテンポラリファイルは、closeが行われると削除される。ただし、実際に削除されるのは GC(ガーベージコレクション) が発生したとき。close(true)を行うことですぐに削除することもできる。
File.rename(before, after)
ファイル名を変更するクラスメソッド。
File.delete(filename)
ファイルを削除するクラスメソッド。
File.basename(path [, suffix])
パスの最後の "/" 以降を返すクラスメソッド。
suffix を与えると、その部分を取り除いて返す。
File.basename('/home/ruby.rb', '.rb') #=> ruby
File.dirname(path)
ディレクトリのパスを返すクラスメソッド。
File.dirname('/usr/bin/ruby') #=> /usr/bin
File.split(path)
パスをディレクトリとファイルに分けて配列で返すクラスメソッド。
カレントのファイルパスを与えると、ディレクトリは "." になる。
File.split('/home/hamasyou/ruby.rb')
#=> ['/usr/hamasyou', 'ruby.rb']
Dir.pwd
現在のディレクトリを返すクラスメソッド。
Dir.chdir(path)
現在のディレクトリを変更するクラスメソッド。
Dir.glob(filename)
filename にマッチするファイル名を返すクラスメソッド。
filename にワイルドカードが使える。
"*" 全ファイルにマッチ
"*/*.html" サブディレクトリの .html ファイルにマッチ
" **/*.html" カレントディレクトリ以下の .html ファイルにマッチ
Dir.mkdir(dirname)
ディレクトリを作成するクラスメソッド。
Dir.rmdir(dirname)
ディレクトリを削除するクラスメソッド。
削除するディレクトリは中身が空でないといけない。
dir.each {|f| ...}
開いているディレクトリに含まれるコンテンツを返す。
カレントディレクトリ(.)、親ディレクトリ(..)、
その他ディレクトリ、ファイルが返される。
=== ftools を require すると使えるメソッド ===
File.copy(from, to)
ファイルをコピーする。
File.move(from, to)
ファイルを移動する。
File.compare(from, to)
ファイルを比較する。
File.makedirs(path)
深いディレクトリも再帰的に作成する。
参考
- たのしいRuby を読み終わったらコレ!
- 達人プログラマによるRuby解説本
