既にRubyでの簡単なプログラムを作った経験があるという前提で, 手短に見直して把握できる程度の説明をこの章にまとめておく。
ソースプログラムをファイルに記述する上での特徴をまとめる。
do ... end
{ ... }
_
で書き始める$
で始まる変数はグローバル変数@
で始まる変数はインスタンス変数で定義したクラス内全域で有効Rubyの主要な制御構造を示す。
if
- 分岐
if 条件1 then 節1 elsif 条件2 then 節2 : : else 節else end
条件1 が成り立つときは 節1 を, 条件2 が成り立つときは 節2 を,…, いずれでもないときは 節else を, 評価する。
while
- 条件が成り立つ間の繰り返し
while 条件 節 end
条件 が真である間 節 を繰り返す。
case
- 選択
case 値 when 値1[,値1b,…] 節1 when 値2 節2 else 節else end
case
直後に書いた 値 を後続する
when
の後の値と比較し,一致したらそのすぐ後の
節を評価する。どの when
の値にも一致しなかった
ときは else
後の節に進む。
break
while
などの構文を抜けて次に進む。
next
while
などの繰り返し構文の次の回に進む。
条件の評価からやりなおす。
redo
while
などの繰り返し構文の節先頭に進む。
条件の評価はしない。
制御構造の条件の部分に利用する比較のための演算子のうち 本書で必要なものを示す。
演算子 | 意味 |
---|---|
== | 左辺と右辺が等しいか |
< | 左辺が右辺より小さいか |
<= | 左辺が右辺以下か |
> | 左辺が右辺より大きいか |
>= | 左辺が右辺以上か |
&& | 「かつ」 |
|| | 「または」 |
! | 否定 |
not | 否定 |
条件が成り立つ場合は,「真」を表す true
が,
成り立たない場合は「偽」を表す false
を返す。
なお,Rubyでは空を意味する値に nil
があり,
これも「偽」の役割を持つ。したがって,nil
でも false
でもない値が「真」の役割をする。
&&
,||
と同じ意味で,
演算優先順位の低い and
と or
がある。
これはある条件の成否によって処理を行なうかどうかを決める
短縮表記として有用である。
条件 and 文 条件 or 文
のように書くと,前者は条件が成り立つときに後続する文を評価し, 後者は条件が成り立たないときに後続する文を評価することになる。
また,条件演算子 ?
も文の短縮化に有用である。
条件 ? 式1 : 式2
は,この表現全体として値を返す。 条件 が成り立つときには式1の値を, そうでないときには 式2 の値を返す。
数値の演算は他の言語と共通するものが多い。
ただし,C由来のインクリメント/デクリメント演算子の
++
と --
はない。
演算子 | 意味 |
---|---|
+ | 加算 |
* | 乗算 |
- | 減算 |
/ | 除算 |
% | 剰余 |
** | べき乗 |
= | 通常代入 例: x=5 でxに5が代入される |
+= | 加算代入 例: x+=5 でxが5増える |
*= | 乗算代入 例: x*=5 でxが5倍になる |
-= | 減算代入 例: x-=5 でxが5減る |
/= | 除算代入 例: x/=5 でxが1/5になる |
%= | 剰余代入 例: x%=5 は x = x%5 と同じ |
**= | べき乗代入 例: x**=5 は x=x**5と同じ |
メソッド定義は以下の形式で行なう。
def メソッド(引数リスト) 定義本体 end
の形式で メソッド を定義する。
def foo(x, y) end
とすると,2つの引数を取るメソッド foo
が定義される。
x
と y
は仮引数と呼び,
呼ぶときに渡された2つの値がその順番で代入される。定義した
foo
メソッドを呼ぶときは,
foo(a, b)
のようにする。メソッドの引数を省略可能とすることもできる。
def bar(x, y="foo") end
とすると第2引数を省略可能になる。省略時の値が "foo"
となる。
times
- 回数指定の繰り返し
N.times do 繰り返し本体 end
繰り返し本体 を N 回繰り返す。
upto
と downto
- 数えながらの繰り返し
M.upto(N) do |変数| 繰り返し本体 end
整数 M から N まで(M < N)を 変数 に代入しながら繰り返し本体を繰り返す。
1.upto(10) do |x| printf("%d, ", x) end
は1〜10までの整数を全てカンマ区切りで出力する。
downto
は,upto
の逆で
大きい数から小さい数に向かって繰り返しを行なう。
step
- 数えながらの繰り返し
B.step(G, S) do |変数| 繰り返し本体 end
初期値 B から始めて,Sずつ 数を増やしながら G まで変化する数を 変数 に代入しながら繰り返しを行なう。 以下に例を示す。
s = 0 1.step(99, 2) do |n| s += n end printf("1〜99の合計は %d です。\n", s)
for
- 配列要素すべてに対する繰り返し
for 変数 in 配列 do 繰り返し本体 end
配列 の要素を1つずつ取り出し順次 変数 に代入して繰り返し本体を繰り返す。
each
- 配列要素すべてに対する繰り返し
配列.each do |変数| 繰り返し本体 end
for
と同じ働きを持つ。
値の1次元的な集合を表すのが配列。 Rubyでは大括弧内にカンマ区切りで表記する。 先頭要素は添字0でアクセスする。 Rubyでは配列の要素にどんな種類の値が入っても構わない。
[1, nil, "foo", [2, true], 3.14]
という配列も可能で,これは第0要素から順に
整数の1,nil
,文字列の "foo"
,
配列の [2, true]
,浮動小数点数の3.14が格納されている。
配列に備わっている代表的なメソッドには以下のものがある。
length | 要素数を返す |
sort | 並べ替え |
reverse | 逆順化 |
uniq | 重複要素の削除 |
delete(val) | 指定要素の削除 |
shift | 先頭要素を取り出して削除 |
unshift(val) | 要素を配列の先頭に追加 |
<< val | 要素を配列の末尾に追加 |
index(val) | 指定要素の位置を返す |
ブロックを伴うメソッドで,要素を1つずつ変数に代入し,ブロックの評価を 繰り返して加工したり集めたりすることができる。
each {|変数| ブロック} |
要素を1つずつ取り出し変数 に順次代入して ブロック を繰り返す |
collect {|変数| ブロック} |
要素を1つずつ取り出し変数 に順次代入して ブロック を評価した値を配列で返す |
select {|変数| ブロック} |
要素を1つずつ取り出し変数 に順次代入して ブロック を評価して真になったときの要素を集めた配列を返す |
reject {|変数| ブロック} |
要素を1つずつ取り出し変数 に順次代入して ブロック を評価して真になったときの要素を以外 を集めた配列を返す |
reject! {|変数| ブロック} |
reject と同様だが元の配列自身を直接操作して
該当要素を取り除く |
配列要素を一つずつ取り出して繰り返す処理は以下のように
each
や for
を利用する。
# eachを使う場合 array.each do |val| # valに要素が順に入る end # forを使う場合 for val in array do # valに要素が順に入る end
配列の添字を任意の値にできるものがハッシュである。
ハッシュ値のリテラル表記はブレース(中括弧; {}
)を用いる。
v = {key1 => value1, key2 => value2, key3 => value3, ...}
これは以下のように代入するのと同じである。
v = Hash.new v[key1] = value1 v[key2] = value2 v[key3] = value3 :
ハッシュの各要素にアクセスするときの記法は配列と同じく
ブラケット(大括弧; [ ]
)を用いる。
x = v[key]
ハッシュに備わっている代表的なメソッドには以下のものがある。
length | キーと値のペアの個数を返す |
keys | キーのみからなる配列を返す |
values | 値のみからなる配列を返す |
has_key?(key) |
keyと一致するキーが存在するか(trueかfalseが返る) |
delete(key) |
keyと一致するキーと対応する値を削除する |
配列のメソッドでブロックを伴って繰り返すものは,ブロック変数を 2つにするとハッシュで用いることができる。1つ目の変数にはキー, 2つ目の変数にはそれに対応する値が同時に代入されブロックが繰り返される。
ハッシュのキーと値を一組ずつ取り出して繰り返す処理は以下のように書く。
# eachを使う場合 hash.each do |key, val| # keyにキー,valに値が順に入る end # forを使う場合 for key, val in hash do # keyにキー,valに値が順に入る end
ハッシュのキーに存在しないものを指定したときは通常nil
を返す。
hash["detarame"] # 存在しないキーだとする nil
存在しないキーに対する値は default=
メソッドで変更できる。
hash.default = "ありまへん" hash["detarame"] ありまへん
文字列リテラルはダブルクォート,またはシングルクォートで括って表す。
# いずれも同じ foo という文字列 "foo" 'foo'
ダブルクォートの中では #{ }
による値の展開が行なわれる。
x = 5 "xの値は#{x}です" xの値は5です。 'xの値は#{x}です' xの値は#{x}です。
文字列に対する操作の代表的なメソッドを示す。[ ]
内の添字は0から始まる。添字に負の整数を与えると末尾から数える。
str.length | 文字列の長さを返す |
str1+ str2 |
文字列どうしの結合 |
str* N |
文字列のN回繰り返し |
str[N] |
文字列のN文字目の取り出し(str[0]が先頭) |
str[B,L] |
B文字目からL文字分の部分文字列を返す |
str[B..E] |
B文字目からE文字目までの部分文字列を返す |
Rubyプログラムにデータを与えるには,
./program.rb datafile.txt
./program.rb (その1) データ1 データ2 : [C-d] ./program.rb < datafile.txt (その2) cat datafile.txt | ./program.rb (その3)
の方法がある。
1と2はgetsのみで,
while line=gets 〜処理〜 end
という構成で,3はopenメソッドを用い
open(file, "r") do |handle| while line=handle.gets 〜処理〜 end end
という構成で作成する。
データをファイルに書き出すにはopenメソッドのモード指定に
"w"
を指定する。
open(outfile, "w") do |handle| handle.print(....) end
以下のプログラムは output.txt ファイルに,1から10までの数字を書き出す。
open("output.txt", "w") do |w| 1.upto(10) do |x| w.printf("%d\n", x) end end
openメソッドで指定できるモードを以下に示す。このモードは Cに近いプログラミング言語ではほぼ共通である。
"r" | 読み込み用で開く。 |
"r+" |
読み書き両用で開く。読み込みはファイル先頭から行なわれる。 |
"w" |
書き込み用で開く。同名ファイルがあったら空にしてから書き込む。 |
"w+" |
読み書き両用で開く。既存のファイルがあったら空にしてから書き込む。 |
"a" |
書き込み用で開く。既存のファイルがあったら末尾に追加して書き込む。 |
"a+" |
読み書き両用で開く。既存のファイルがあったら末尾に追加して書き込む。 |
モード指定のアルファベットに,"b"
を追加するとバイナリモードの指定になり,文字列として扱う場合の文字コード
変換処理を無効化する。
Ruby1.9以降では,プログラム中に英字以外の文字を含ませる場合に, その文字コードを明示する必要がある。プログラムファイルの1行目か2行目に, 以下の1から3の書式いずれかで文字コードを記述する。
# coding: Encoding
# -*- coding: Encoding -*-
# vim:fileencoding=Encoding
2と3の方法はテキストエディタに保存文字コードを指定する記法で, それぞれEmacs,vim 用のものである。Rubyはその記法も解釈するので, 利用するテキストエディタに即した記法を利用すると便利である。
Encodingには用いる文字コード体系に対応して, 以下のいずれかの文字コード名を指定する。
文字コード | 文字コード名 |
---|---|
UTF-8 | utf-8 |
日本語EUC | euc-jp |
シフトJIS | shift_jis |
Rubyが認識する文字コード名一覧は 以下のようにして得ることができる(1.9以降)。
ruby -e 'p Encoding.name_list'
2,3の記法を用いる場合は,得られる一覧のうち テキストエディタの認識する文字コード名と共通のものを選ぶ必要がある。
これもRuby1.9以降で意識すべき点で,プログラムファイルの文字コードと 文字列として読み込むデータの文字コードは原則として統一する。 データが別の文字コードの場合は,入出力のときに変換した上で処理を進める。
ファイルからのデータ読み込みで,ファイルの文字コードが決まっている場合は openのときのモード指定に変換先文字コード指定を付け加えることで自動変換が 行なわれる。たとえば,プログラムファイルが utf-8 で, JISコード(iso-2022-jp)の入力ファイルを読み込み, なんらかの処理をした結果を euc-jp のファイルに書き出す場合は以下のようにする。
#!/usr/bin/env ruby # coding: utf-8 open("jis.txt", "rb:iso-2022-jp:utf-8") do |j| #JISコードはバイナリモードで open("euc.out", "w:euc-jp") do |e| while line=j.gets print line e.print line end end end
openメソッドのモード指定の後ろにコロンで区切って 「外部Encoding」あるいは「外部Encoding:内部Encoding」 の指定を追記でき,外部Encodingを内部Encodingに自動変換して読み込んだり, あるいはその逆方向に変換してデータファイルに書き込ませることができる。
正規表現は / /
で括る。
if /正規表現/ =~ 文字列 then 〜文字列がマッチする場合の処理〜 end
文字列から正規表現を生成するには Regexp.new
を利用する。
reg = Regexp.new(正規表現) if reg =~ 文字列 then 〜文字列が正規表現 にマッチする場合の処理〜 end
正規表現では,特定の文字を探すための特別な働きを持つ メタキャラクタを利用できる。主なものを以下に示す。
. (ピリオド) | 任意の1字 |
[文字クラス] | 選択(下記参照) |
* | 直前の正規表現の0回以上の繰り返し |
+ | 直前の正規表現の1回以上の繰り返し |
? | 直前の正規表現の0か1の繰り返し |
{N} | 直前の正規表現の N回の繰り返し |
{N,} | 直前の正規表現の N回以上の繰り返し |
{M,N} | 直前の正規表現の M〜N回の繰り返し |
^ | 行頭 |
$ | 行末 |
\w | 英数字 [0-9A-Za-z_] |
\W | 非英数字(\w の逆) |
\s | 空白文字 [ \t\n\r\f] |
\S | 非空白文字(\s の逆) |
\d | 数字 [0-9] |
\D | 非数字(\d の逆) |
\b | 単語境界 |
\B | 非単語境界 |
文字クラスの利用例をいくつか示す。
[abc123] | a, b, c, 1, 2, 3のどれか1字 |
[a-z] | a〜zのどれか1字 |
[^a-z] | a〜z以外のどれか1字 |
[-0-9] | ハイフンまたは0〜9のどれか1字 |
[\[\]] | [ または ] のどちらか1字 |
正規表現パターンの一部を ( )
で括るとその部分を一塊にできる。
/abcd?efg/ /(abcd)?efg/
たとえば前者は ?
が直前の d だけに作用するが,
後者は abcd
一まとめに対して作用する。また,
括弧でグルーピングした部分にマッチした文字列は,
同じ正規表現内では \数字
,
正規表現マッチを抜けた直後では $数字
で参照できる。数字 には何番目の括弧かを指定する。
たとえば以下の例を考える。
/(['"]?)[a-z]+\1/ =~ "foo" /(['"]?)[a-z]+\1/ =~ "'foo'"
正規表現自体は「シングルクォートまたはダブルクォートが1回,または0回
現れた後ろに,小文字英字が1回以上続き,その後ろにグルーピングの1番目
が来る」という意味で,1行目で照合している文字列「foo」の場合は,
クォートがないので第1グルーピングでは0回マッチ,つまり空文字なので
\1
が空文字に置き換えられる。
2行目で照合している文字列「'foo'」の場合は,シングルクォートが
第1グルーピングでマッチするため,\1
はシングルクォート('
)に置き換えられる。
正規表現のマッチングから抜けた直後は $1
に
空文字列,またはシングルクォートが代入されている。その他,
正規表現マッチ直後で利用できる以下の変数も有用である。
$& | 照合文字列のうち正規表現にマッチした部分全体 |
$` | 照合文字列のうち正規表現に マッチした部分より前の部分 |
$' | 照合文字列のうち正規表現に マッチした部分より後ろの部分 |
メタキャラクタの *
と +
は,マッチするものが最も長くなるようにマッチングを試みる(最長マッチ)。
/Th.*s/ =~ "This is a pen." => 0 $& => "This is"
*?
と +?
は最短マッチを試みる。
/Th.*?s/ =~ "This is a pen." => 0 $& => "This"
指定したパターンの照合方式を調整するために正規表現オプションを指定できる。
正規表現オプションは /…/
の直後に1文字,あるいは,
Regexp.new()
の第2引数に定数を与えて指定する。
リテラル表記 | Regexp.new第2引数 | 意味 |
---|---|---|
/.../i | Regexp::IGNORECASE | 英大文字小文字を同一視する|
/.../m | Regexp::MULTILINE | 改行文字も . でマッチする |
正規表現にも文字コードの概念があり,正規表現と照合対象の文字列 の文字コードに食い違いは許されない(Ruby1.9以降の場合)。 プログラムの記述されたファイルの文字コードが正規表現の文字コードとなり, 照合したい文字列の文字コードと異なるとエラーが発生する。 そのような場合は,照合文字列を正規表現の文字コードに変換する。
Rubyマニュアル 正規表現 も参照。