C/C++, Java は使える、大学で ML とか Scheme もやった、そろそろスクリプト言語を覚えたい、という人向けに、一時間で Ruby がある程度 (日常的な処理が少しは出来る程度) 使える様になるまでをまとめます。他のスクリプト言語の知識は仮定しません。
このページでは、例示による学習を期待しています。すなわち、例と結果を与えられることでその意味を理解するということです。これが出来ないと一時間で使えるようになるのは厳しい。オブジェクト指向、正規表現と聞いて一つでも意味が分からない人は別のところで勉強してください。速習を目指しているので、細かいところは全部割愛しています。とりあえず使えるようになった後にちゃんとした入門書を読んでください。
Ruby はインストールされているものとします。とりあえず ruby と叩いて起動。
$ ruby
出力できなければ話にならないので、まず出力を覚えます。puts
, print
ぐらいを覚えておけば良いでしょう。前者は勝手に改行し、後者はしません。
print "fugahoge\n" puts "fugahoge" [EOF] fugahoge fugahoge
ruby と叩いて得られるものは対話実行環境ではないので、明示的に EOF を送らないと実行されません。それは面倒なので irb と叩いて interactive ruby を起動します。
irb(main):001:0> puts "fugahoge" fugahoge => nil
これで interactive に結果を得られます。=> 以下は式を評価した結果が返ります。この場合 nil が返っています。>
の前はプロンプトですが、ここでごちゃごちゃ書くのは面倒なので以降では省略します。
puts
, print
以外に p
も覚えましょう。Ruby では任意のものはオブジェクトであり、p
はその中身を見るための関数です。
> p "fugahoge" "fugahoge" => nil
文字列はそのまま文字列が返される、と。
あと足し算とか適当に試してみること。例えば次の文達。
> puts (1 + 2) > puts ("fugahoge" * 3) > puts > puts "Hellow"; puts "Hellow"
Ruby はスクリプト言語らしく行指向なので、改行で区切りになってしまいます。;
で同じ行に二つの命令を書けます。
以降では irb と ruby を混同して使います。ruby スクリプトは、ruby script.rb と起動するか、script の先頭に #!/usr/bin/ruby (もしくは #!/usr/local/bin/ruby) を付けて実行します。
大体のオブジェクトはあなたが思っている通りの型がつきます。1 は Integer だとか、"fugahoge" は String だとか。
Ruby では全てはオブジェクトだから、Integer もオブジェクトです。Integer にはいくつかメソッドがあり、例によって object.method
でメソッドを呼べます。
> 10.divmod(3) => [3, 1]
おっと、Array が返ってきました。Array はあなたが思っている通りにアクセス可能です。
> s = [1, 2, "fugahoge"] > s[0] > s[1] > s[2]
Array の添え字を負の数にすると、末尾からの要素をさすようになります。ちょっと汚い様な。
> s[-1]
とりあえず to_s を覚えておきましょう。String になります。
> s.to_s
あとは to_i (Integer へ), to_f (Float へ) は覚えておきましょう。
ちなみに、string で n 番目の文字を取り出す場合 s[n] としてしまうと、n 番目の文字の文字コードが得られてしまうので注意。s[n, 1] とすれば、n 番目の文字だけからなる string が返ります。
Array で覚えて便利なのは、each, size あたり。
> [1, 2].size => 2 > [1, 2].each { |x| puts x } 1 2 => [1, 2]
{ |x| ... }
の部分をブロックといいます。まあ、ただのラムダクロージャだと思えば生活できます(実際には違うが)。each の後にブロックを持ってくることで各要素に対してイテレーションが可能です。もちろん x
に値が入っています。
ちなみに、こんなことも出来ます。
10.times { |x| print x }
Array 以外の構造としては Hash を覚えておくと便利です。C++ の (hash)map だと思えば OK.
> h = {"a" => 1, "b" => 2 } > h["a"] => 1 > h["b"] => 2 > h["c"] => nil
対応する要素がない場合は nil が返ります。
if, while は使えないと話になりません。
if は次の形で使います。
if condition
expr1
else
expr2
end
# else を省略した場合
if condition
end
condition では、false, nil 以外は true とみなされます。Integer の 0 も true であることに注意。
while は次の形で使います。途中で break
することも可能です。
while condition expr end
if
, while
とも、一行で書きたいときは ;
をうまく使いましょう。
> i = 0; while i < 10; puts i; i = i + 1; end
繰り返しには、上で述べた times メソッドを使うのもあり。
関数も作れないと話にならないので、関数を作る方法を学びます。関数は def
で定義します。
def add(x, y) x + y end def say_hello puts "hello" end
最後に評価した値が返り値になります。引数がないものは引数部分を省略できます。
次にクラスを作ります。Ruby では色々なものがクラスで定義されているので、クラスが使えないとたぶんまずいでしょう。
class Foo def initialize(x) @var = x end def method1 ... end def method2(x, y) ... end end x = Foo.new(10)
これで class Foo が定義されました。Foo のコンストラクタは initialize
という名前で定義します。インスタンス変数は @var
というように頭に @
を付けます。クラス変数は @@var
と頭に二個 @
を付けます。インスタンス変数は、いわゆる private なので、必要ならば get/set アクセッサを定義しましょう。
ちなみに、何もつけないとローカル変数、$
を付けるとグローバル変数になります。先頭を大文字で始めると定数となり、値が変更できなくなります。変数 var が定義されているかどうかは、var.defined?
と defined?
を使います。
Ruby のクラスは、何も指定しなければ Object
というクラスから派生することになっています。Object には .to_s 等のメソッドが定義されています。
せっかくスクリプトを使うのだから正規表現を使わないともったいない、ということで正規表現の使い方を覚えましょう。正規表現自体は知っていると仮定します。
とりあえず、マッチしているかどうかの判定、マッチしている部分を抽出、そしてマッチしている部分を置換、これら3つが出来る様になればかなり生活出来ます。
正規表現は、/
で前後をくくって表します。
/a.*b/ # a で始まり b で終わる文字列
文字列に正規表現がマッチしている部分があるかどうかを判定するには、=~
を使います。
"abc" =~ /a.*c/ #=> 真 "bde" =~ /a.*c/ #=> 偽
括弧を使えば、左から数えて n 番目の括弧の中の正規表現にマッチした文字列を $n
で得られます。
> "spring summer fall winter" =~ /((\w*)\s)*/ => 0 > $1 "fall " > $2 "fall"
何度も括弧の中でマッチする場合は最後にマッチしたものが得られます。
バックスラッシュ表記が出てきましたが、次のものを覚えておけばよいでしょう。
置換には、sub, gsub を使いましょう。sub は最初にマッチした部分だけを書き換え、gsub はマッチした部分全部を書き換えます。
> s = "spring summer fall winter" > s.sub(/\w+/, "w") => "w summer fall winter" > s.gsub(/\w+/, "w") => "w w w w"
いくら処理が出来るようになっても入力が出来ないと意味がないので出入力を覚えましょう。
とりあえずファイルを一行ずつ読めれば生活に困らないでしょう。次のようにかければよいでしょう。
f = open(readfile) g = open(writefile) while x = f.gets g.print x end f.close
スクリプトを指定したときに、いくつかファイルを引数として指定したとします。このとき、ARGF
は、それらのファイルを全部つなげた様なものになります。引数を指定しなければ標準入力になります。ということで、Ruby では cat は次のように書けます。
while line = ARGF.gets print line end
ちなみに、諸般の理由により ARGF.gets
は gets
とだけ書いても OK.
これだけ知ってれば簡易な word count が作れるかと思いますが、はたして。
$lc = $wc = $cc = 0 def wc(line) in_word = false i = r = 0 while i < line.size do if line[i, 1] == " " || line[i, 1] == "\t" || line[i, 1] == "\n" || line[i, 1] == "\r" if in_word; r += 1; end in_word = false else in_word = true; end i += 1 end if in_word; r += 1; end r end while line = gets $lc += 1 $cc += line.size $wc += wc(line) end printf("line -- %d\nword -- %d\nbyte -- %d\n", $lc, $wc, $cc)
もっと簡単に書く方法はあるのだけれど。挙動を wc にあわせているわけではないので、行の数が一行ずれる場合有り。さらに、このコードはここで解説したことをなるべく盛り込もうという趣旨のため必要以上にめんどうくさいことをしているので注意。